<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ashutosh Writes]]></title><description><![CDATA[Ashutosh Writes is a tech-focused blog where practical learning meets real-world development. Here, you’ll find clear and engaging articles on web development, Python, Java, and broader software engineering topics. From step-by-step project tutorials to insights that simplify complex concepts, the blog is designed to help developers build, learn, and grow—whether you’re just starting out or sharpening your skills.]]></description><link>https://blog.ashutoshkrris.in</link><image><url>https://cdn.hashnode.com/uploads/logos/61c1acb4a90dea775da8262b/e011bc46-99ec-4290-a669-b54baa250960.png</url><title>Ashutosh Writes</title><link>https://blog.ashutoshkrris.in</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 21:31:57 GMT</lastBuildDate><atom:link href="https://blog.ashutoshkrris.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Spring Boot @Value Property Order Explained]]></title><description><![CDATA[If you’ve ever been in a Spring Boot interview, you’ve probably come across this question:

“Where does Spring Boot look for @Value("${my.property:DEFAULT_VALUE}"), and in what order?”

At first, it might sound straightforward, but it actually tests ...]]></description><link>https://blog.ashutoshkrris.in/spring-boot-value-property-order-explained</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/spring-boot-value-property-order-explained</guid><category><![CDATA[Java]]></category><category><![CDATA[interview questions]]></category><category><![CDATA[interview]]></category><category><![CDATA[Springboot]]></category><category><![CDATA[backend]]></category><category><![CDATA[Backend Development]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Wed, 29 Oct 2025 11:48:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761738465610/ca4a7f84-eba1-4059-b827-39dcc962c77a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve ever been in a Spring Boot interview, you’ve probably come across this question:</p>
<blockquote>
<p>“Where does Spring Boot look for <code>@Value("${my.property:DEFAULT_VALUE}")</code>, and in what order?”</p>
</blockquote>
<p>At first, it might sound straightforward, but it actually tests a developer’s understanding of <strong>how Spring Boot resolves configuration properties</strong> — a concept that directly impacts how applications behave across environments.</p>
<p>Understanding the configuration hierarchy in Spring Boot is essential because it helps you:</p>
<ul>
<li><p>Debug issues when the wrong value is picked up.</p>
</li>
<li><p>Control how environment variables and external configurations override defaults.</p>
</li>
<li><p>Manage different environments such as development, staging, and production in CI/CD pipelines.</p>
</li>
</ul>
<p>In this article, we’ll look at how <code>@Value</code> works, the exact order in which Spring Boot looks for property values, and why this knowledge is crucial for building predictable and maintainable applications.</p>
<h2 id="heading-understanding-the-value-annotation">Understanding the <code>@Value</code> Annotation</h2>
<p>The <code>@Value</code> annotation in Spring Boot is used to <strong>inject values</strong> into fields directly from property sources such as <code>application.properties</code>, <code>application.yml</code>, environment variables, or command-line arguments. It allows you to bind configuration values to variables in your code without hardcoding them.</p>
<p>Here’s a simple example:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Value("${my.property:DEFAULT_VALUE}")</span>
<span class="hljs-keyword">private</span> String myProperty;
</code></pre>
<p>In this example:</p>
<ul>
<li><p><code>my.property</code> is the <strong>key</strong> whose value Spring Boot will try to resolve.</p>
</li>
<li><p><code>DEFAULT_VALUE</code> is the <strong>fallback value</strong> that will be used <strong>if the property is not found</strong> in any configuration source.</p>
</li>
</ul>
<p>This default value mechanism is very useful. It ensures your application does not fail to start even if a configuration is missing. Instead, Spring Boot will inject the specified default, keeping your application stable and predictable.</p>
<p>Using <code>@Value</code> is a simple way to access configuration properties for small or single-value injections. For more complex or grouped configurations, developers often use <code>@ConfigurationProperties</code>, which we’ll discuss later.</p>
<h2 id="heading-where-does-spring-boot-look-for-properties-order-of-resolution">Where Does Spring Boot Look for Properties (Order of Resolution)</h2>
<p>When you use <code>@Value</code> or any other property injection mechanism, Spring Boot doesn’t just look in one place for configuration values. It searches across <strong>multiple sources</strong> in a specific <strong>priority order</strong>.</p>
<p>This order determines which value is finally injected when the same property key appears in different places. The <strong>higher the source is in the list</strong>, the <strong>greater its priority</strong>.</p>
<p>Here’s the general order in which Spring Boot resolves properties (based on the <code>SpringApplication</code> configuration sources):</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Priority</td><td>Source</td><td>Example / Notes</td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td><strong>Command-line arguments</strong></td><td>e.g. <code>--my.property=value</code> when running the application</td></tr>
<tr>
<td>2</td><td><strong>Java System properties</strong></td><td>e.g. <code>-Dmy.property=value</code></td></tr>
<tr>
<td>3</td><td><strong>OS environment variables</strong></td><td>e.g. <code>export MY_PROPERTY=value</code></td></tr>
<tr>
<td>4</td><td><strong>Application properties or YAML files</strong></td><td>Located in <code>src/main/resources/application.properties</code> or <code>.yml</code></td></tr>
<tr>
<td>5</td><td><strong>Profile-specific configuration files</strong></td><td>e.g. <code>application-dev.properties</code> when <code>spring.profiles.active=dev</code></td></tr>
<tr>
<td>6</td><td><strong>External configuration files</strong></td><td>Files located in a <code>/config</code> directory outside the packaged JAR</td></tr>
<tr>
<td>7</td><td><strong>JNDI attributes</strong></td><td>Used in servlet containers or enterprise environments</td></tr>
<tr>
<td>8</td><td><strong>Random values</strong></td><td>e.g. <code>${random.uuid}</code>, <code>${random.int}</code> generated by Spring Boot</td></tr>
<tr>
<td>9</td><td><strong>Default value in code</strong></td><td>The fallback provided in <code>@Value("${my.property:default}")</code></td></tr>
</tbody>
</table>
</div><p>Spring Boot checks these sources <strong>in order</strong> — from top to bottom — and uses the <strong>first value it finds</strong> for a given property key.</p>
<p>This hierarchy allows you to easily <strong>override configurations</strong> at runtime without changing your code. For example, values from command-line arguments or environment variables can override those in your application files, which is especially useful for deploying the same codebase to multiple environments like development, testing, and production.</p>
<h2 id="heading-example-demonstration">Example Demonstration</h2>
<p>Let’s look at a simple example to understand how Spring Boot decides which property value to use when multiple sources define the same key.</p>
<p>Imagine the following project structure:</p>
<pre><code class="lang-plaintext">src/
 └─ main/resources/
     ├─ application.properties
     ├─ application-dev.properties
</code></pre>
<h3 id="heading-step-1-define-properties-in-both-files">Step 1: Define properties in both files</h3>
<p><strong>application.properties</strong></p>
<pre><code class="lang-java">my.property=HelloFromApplication
</code></pre>
<p><strong>application-dev.properties</strong></p>
<pre><code class="lang-java">my.property=HelloFromDevProfile
</code></pre>
<h3 id="heading-step-2-use-value-in-your-code">Step 2: Use <code>@Value</code> in your code</h3>
<pre><code class="lang-java"><span class="hljs-meta">@Value("${my.property:DefaultHello}")</span>
<span class="hljs-keyword">private</span> String message;
</code></pre>
<h3 id="heading-step-3-run-the-application-with-different-configurations">Step 3: Run the application with different configurations</h3>
<h4 id="heading-case-1-default-profile-no-active-profile">Case 1: Default profile (no active profile)</h4>
<p>If you run your Spring Boot app normally:</p>
<pre><code class="lang-bash">java -jar myapp.jar
</code></pre>
<p>Spring Boot will load <code>application.properties</code> and inject the value:</p>
<pre><code class="lang-bash">HelloFromApplication
</code></pre>
<h4 id="heading-case-2-active-profile-set-to-dev">Case 2: Active profile set to “dev”</h4>
<p>If you run:</p>
<pre><code class="lang-bash">java -jar myapp.jar --spring.profiles.active=dev
</code></pre>
<p>Spring Boot will load both <code>application.properties</code> and <code>application-dev.properties</code>, but <strong>the profile-specific file has higher priority</strong>.<br />So the value becomes:</p>
<pre><code class="lang-bash">HelloFromDevProfile
</code></pre>
<h4 id="heading-case-3-override-from-the-command-line">Case 3: Override from the command line</h4>
<p>Now, if you run:</p>
<pre><code class="lang-bash">java -jar myapp.jar --my.property=HelloFromCLI
</code></pre>
<p>Command-line arguments take the <strong>highest priority</strong>, so this overrides everything else:</p>
<pre><code class="lang-bash">HelloFromCLI
</code></pre>
<h4 id="heading-case-4-no-property-found-anywhere">Case 4: No property found anywhere</h4>
<p>If you remove the property from all configuration files and don’t pass it as an argument, Spring Boot uses the default value given in the code:</p>
<pre><code class="lang-bash">DefaultHello
</code></pre>
<p>This example shows how Spring Boot’s property resolution order allows flexible configuration management. You can define defaults in your code, keep environment-specific values in property files, and still override them at runtime when needed.</p>
<h2 id="heading-common-pitfalls">Common Pitfalls</h2>
<p>Even though Spring Boot’s configuration system is powerful, it’s easy to run into small mistakes that cause unexpected behavior. Here are some common pitfalls developers face when working with <code>@Value</code> and property resolution.</p>
<h3 id="heading-1-forgetting-to-set-the-active-profile">1. Forgetting to Set the Active Profile</h3>
<p>Spring Boot supports profile-specific configuration files, such as <code>application-dev.properties</code> or <code>application-prod.properties</code>.<br />However, these files are only used when the corresponding profile is active. If you forget to set the profile, Spring Boot will ignore those files and fall back to the default <code>application.properties</code>.</p>
<p>For example:</p>
<pre><code class="lang-bash">java -jar myapp.jar --spring.profiles.active=dev
</code></pre>
<p>Without this argument, your <code>application-dev.properties</code> file won’t be loaded at all.</p>
<h3 id="heading-2-unintentional-property-overrides">2. Unintentional Property Overrides</h3>
<p>Because Spring Boot merges multiple property sources, it’s possible to <strong>accidentally override</strong> values from one source with another.<br />A common case is when an environment variable or command-line argument unintentionally replaces a property defined in your configuration file.</p>
<p>For instance, if your system has an environment variable named <code>MY_PROPERTY</code>, it might override the <code>my.property</code> key from your <code>.properties</code> file. Always check the effective configuration when debugging unexpected values.</p>
<h3 id="heading-3-confusing-value-and-configurationproperties">3. Confusing <code>@Value</code> and <code>@ConfigurationProperties</code></h3>
<p>Both <code>@Value</code> and <code>@ConfigurationProperties</code> are used to inject configuration values, but they serve different purposes.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td><code>@Value</code></td><td><code>@ConfigurationProperties</code></td></tr>
</thead>
<tbody>
<tr>
<td>Best for</td><td>Single values</td><td>Grouped or structured properties</td></tr>
<tr>
<td>Type safety</td><td>Limited</td><td>Strong (binds directly to fields)</td></tr>
<tr>
<td>Supports validation</td><td>No</td><td>Yes</td></tr>
<tr>
<td>Preferred for large configs</td><td>❌</td><td>✅</td></tr>
</tbody>
</table>
</div><ul>
<li><p>Use <code>@Value</code> when you only need a few properties.</p>
</li>
<li><p>Use <code>@ConfigurationProperties</code> when dealing with a group of related configurations (for example, database settings or API credentials).</p>
</li>
</ul>
<p>Choosing the right one helps keep your configuration clean, organized, and easy to maintain.</p>
<h2 id="heading-interview-tip-summary">Interview Tip / Summary</h2>
<p>When asked about property resolution in Spring Boot interviews, it’s not just about recalling the list — it’s about showing that you understand how and why it works that way.</p>
<p>Here are the key points to keep in mind:</p>
<ol>
<li><p><strong>Spring Boot merges multiple property sources</strong> — it doesn’t rely on a single file.</p>
</li>
<li><p><strong>Higher-priority sources override lower-priority ones</strong> — values from the command line or environment variables can replace those in your application files.</p>
</li>
<li><p><code>@Value("${my.property:DEFAULT}")</code> provides a safety net — the default value ensures your application runs even when the property is missing.</p>
</li>
</ol>
<h3 id="heading-quick-mnemonic-to-remember-the-order">Quick Mnemonic to Remember the Order</h3>
<p>You can remember the lookup order with this simple phrase:</p>
<blockquote>
<p><strong>“CLI → System → Env → App → Default”</strong></p>
</blockquote>
<p>Or think of it as:</p>
<pre><code class="lang-plaintext">Command-line arguments
↓
System properties (-D)
↓
Environment variables
↓
Application files (.properties / .yml)
↓
Default value in code
</code></pre>
<p>If you end your interview answer with a short, clear explanation like this:</p>
<blockquote>
<p>“Spring Boot checks multiple property sources in a specific order — starting from command-line arguments, system properties, environment variables, and application files, before finally using the default value provided in code.”</p>
</blockquote>
<p>—you’ll leave a confident and lasting impression.</p>
<h2 id="heading-frequently-asked-questions-faq">Frequently Asked Questions (FAQ)</h2>
<h3 id="heading-1-what-happens-if-a-property-is-missing-and-no-default-value-is-given">1. What happens if a property is missing and no default value is given?</h3>
<p>If a property key cannot be found in any configuration source <strong>and</strong> you haven’t provided a default value in your <code>@Value</code> expression, Spring Boot will throw an exception during startup.<br />For example:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Value("${my.property}")</span>
<span class="hljs-keyword">private</span> String value;
</code></pre>
<p>If <code>my.property</code> is not defined anywhere, you’ll see an error like:</p>
<pre><code class="lang-bash">Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder <span class="hljs-string">'my.property'</span> <span class="hljs-keyword">in</span> value <span class="hljs-string">"<span class="hljs-variable">${my.property}</span>"</span>
</code></pre>
<p>To prevent this, always provide a fallback value:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Value("${my.property:DefaultValue}")</span>
<span class="hljs-keyword">private</span> String value;
</code></pre>
<p>This ensures your application starts smoothly, even when the property is missing.</p>
<h3 id="heading-2-how-does-configurationproperties-differ-from-value">2. How does <code>@ConfigurationProperties</code> differ from <code>@Value</code>?</h3>
<p>While both are used to inject configuration values, they are suited to different use cases:</p>
<ul>
<li><p><code>@Value</code> is ideal for <strong>single values</strong> or small configurations.<br />  Example:</p>
<pre><code class="lang-java">  <span class="hljs-meta">@Value("${server.port:8080}")</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> port;
</code></pre>
</li>
<li><p><code>@ConfigurationProperties</code> is better for <strong>structured or grouped configurations</strong>, such as database or API settings. It binds multiple related properties into a single Java object and supports validation.</p>
<p>  Example:</p>
<pre><code class="lang-java">  <span class="hljs-meta">@ConfigurationProperties(prefix = "app")</span>
  <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppConfig</span> </span>{
      <span class="hljs-keyword">private</span> String name;
      <span class="hljs-keyword">private</span> String version;
  }
</code></pre>
</li>
</ul>
<p>In short, use <code>@Value</code> for simple injections and <code>@ConfigurationProperties</code> for larger, type-safe configurations.</p>
<h3 id="heading-3-can-we-override-properties-at-runtime">3. Can we override properties at runtime?</h3>
<p>Yes, you can override properties <strong>at runtime</strong> without changing your code.<br />Spring Boot allows this through various property sources, such as:</p>
<ul>
<li><p>Command-line arguments</p>
<pre><code class="lang-bash">  java -jar myapp.jar --server.port=9090
</code></pre>
</li>
<li><p>Environment variables</p>
<pre><code class="lang-bash">  <span class="hljs-built_in">export</span> SERVER_PORT=9090
</code></pre>
</li>
<li><p>System properties</p>
<pre><code class="lang-bash">  java -Dserver.port=9090 -jar myapp.jar
</code></pre>
</li>
</ul>
<p>These dynamic overrides are particularly useful in <strong>CI/CD pipelines</strong> or <strong>cloud environments</strong>, where configurations may differ between development, staging, and production.</p>
]]></content:encoded></item><item><title><![CDATA[Core Java Interview Questions: Complete Guide with Answers and Examples]]></title><description><![CDATA[Mastering Core Java is essential for cracking technical interviews at top tech companies. Whether you’re preparing for coding rounds, design discussions, or scenario-based questions, having a solid grasp of Java fundamentals, memory management, multi...]]></description><link>https://blog.ashutoshkrris.in/core-java-interview-questions-complete-guide-with-answers-and-examples</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/core-java-interview-questions-complete-guide-with-answers-and-examples</guid><category><![CDATA[Java]]></category><category><![CDATA[interview]]></category><category><![CDATA[interview questions]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Wed, 15 Oct 2025 10:52:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761403045450/70cdbaf6-8417-4727-a9b8-0cada8bfe8a4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Mastering Core Java is essential for cracking technical interviews at top tech companies. Whether you’re preparing for <strong>coding rounds, design discussions, or scenario-based questions</strong>, having a solid grasp of <strong>Java fundamentals, memory management, multithreading, collections, and design patterns</strong> can set you apart.</p>
<p>This <strong>comprehensive guide covers all the essential Core Java interview questions in 2025</strong>, with clear explanations, comparisons, and <strong>code examples</strong>. From <strong>OOP principles to Java 8 features, JVM internals, and practical real-world scenarios</strong>, you’ll get a complete overview of the concepts that interviewers frequently test.</p>
<p>Use this guide to <strong>boost your Java knowledge, strengthen problem-solving skills, and confidently tackle interviews</strong>, making sure you’re well-prepared for both theoretical and hands-on coding rounds.</p>
<h2 id="heading-object-oriented-programming-concepts">Object Oriented Programming Concepts</h2>
<h3 id="heading-1-what-are-the-principles-of-oop"><strong>1. What are the principles of OOP?</strong></h3>
<p>OOP (Object-Oriented Programming) is based on four main principles:</p>
<ol>
<li><p><strong>Encapsulation</strong> – Bundling data and methods that operate on that data into a single unit (class).<br /> <em>Example:</em> Private fields with public getters/setters.</p>
</li>
<li><p><strong>Abstraction</strong> – Hiding internal implementation details and exposing only essential features.<br /> <em>Example:</em> Abstract classes and interfaces.</p>
</li>
<li><p><strong>Inheritance</strong> – Reusing properties and methods from an existing class into a new class.<br /> <em>Example:</em> <code>class Dog extends Animal</code></p>
</li>
<li><p><strong>Polymorphism</strong> – The ability of objects to take multiple forms.<br /> <em>Example:</em> Method overriding where the same method behaves differently in different subclasses.</p>
</li>
</ol>
<p>These principles together make code <strong>modular, extensible, and maintainable</strong>.</p>
<h3 id="heading-2-difference-between-abstraction-and-encapsulation"><strong>2. Difference between abstraction and encapsulation</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Abstraction</strong></td><td><strong>Encapsulation</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Purpose</strong></td><td>Focuses on hiding implementation details</td><td>Focuses on bundling data and behavior</td></tr>
<tr>
<td><strong>Achieved By</strong></td><td>Abstract classes and interfaces</td><td>Access modifiers (private, public, etc.)</td></tr>
<tr>
<td><strong>Concerned With</strong></td><td>Design level</td><td>Implementation level</td></tr>
<tr>
<td><strong>Example</strong></td><td>Hiding database connection details behind an interface</td><td>Making class variables private and exposing getters/setters</td></tr>
</tbody>
</table>
</div><p><strong>In short:</strong><br />Abstraction hides <em>what</em> is done, Encapsulation hides <em>how</em> it’s done.</p>
<h3 id="heading-3-what-is-inheritance-how-is-it-implemented-in-java"><strong>3. What is inheritance? How is it implemented in Java?</strong></h3>
<p><strong>Inheritance</strong> allows one class to inherit properties and behaviors from another, promoting code reuse.</p>
<p>In Java:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">greet</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Hello!"</span>); }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">greetChild</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Hi from Child!"</span>); }
}
</code></pre>
<p>Here, <code>Child</code> inherits the <code>greet()</code> method from <code>Parent</code>.</p>
<p><strong>Types of inheritance in Java:</strong></p>
<ul>
<li><p>Single</p>
</li>
<li><p>Multilevel</p>
</li>
<li><p>Hierarchical</p>
</li>
</ul>
<blockquote>
<p>Note: Java does <strong>not support multiple inheritance with classes</strong> to avoid ambiguity, but supports it with interfaces.</p>
</blockquote>
<h3 id="heading-4-what-is-polymorphism-types"><strong>4. What is polymorphism? Types?</strong></h3>
<p>Polymorphism allows an object to behave differently based on context.</p>
<p><strong>Types:</strong></p>
<ol>
<li><p><strong>Compile-time polymorphism (Method Overloading):</strong></p>
<ul>
<li><p>Same method name, different parameter lists.</p>
</li>
<li><p>Resolved at compile-time.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="lang-java">    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a)</span> </span>{}
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">(String b)</span> </span>{}
</code></pre>
<ol start="2">
<li><p><strong>Runtime polymorphism (Method Overriding):</strong></p>
<ul>
<li><p>Subclass provides a new implementation of a parent method.</p>
</li>
<li><p>Resolved at runtime using <strong>dynamic method dispatch</strong>.</p>
</li>
</ul>
</li>
</ol>
<p>Polymorphism improves flexibility and scalability in OOP systems.</p>
<h3 id="heading-5-what-is-method-overloading-vs-overriding"><strong>5. What is method overloading vs overriding?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Method Overloading</strong></td><td><strong>Method Overriding</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>When</strong></td><td>Compile-time</td><td>Runtime</td></tr>
<tr>
<td><strong>Class Relationship</strong></td><td>Same class</td><td>Parent-child classes</td></tr>
<tr>
<td><strong>Parameters</strong></td><td>Must differ in type/number/order</td><td>Must be same</td></tr>
<tr>
<td><strong>Return Type</strong></td><td>Can differ</td><td>Must be same or covariant</td></tr>
<tr>
<td><strong>Static Binding</strong></td><td>Yes</td><td>No (uses dynamic binding)</td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Overloading</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">double</span> a, <span class="hljs-keyword">double</span> b)</span> </span>{}

<span class="hljs-comment">// Overriding</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">()</span> </span>{} 
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">A</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">()</span> </span>{} 
}
</code></pre>
<h3 id="heading-6-can-we-override-static-methods"><strong>6. Can we override static methods?</strong></h3>
<p>No.<br />Static methods are <strong>bound at compile-time</strong> (using class reference), not runtime (using object).</p>
<p>If a subclass defines a static method with the same name as the parent class’s static method, it <strong>hides</strong> the parent method — it’s not overriding.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">greet</span><span class="hljs-params">()</span> </span>{} 
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">greet</span><span class="hljs-params">()</span> </span>{} 
} <span class="hljs-comment">// Method hiding</span>
</code></pre>
<h3 id="heading-7-can-a-constructor-be-overridden"><strong>7. Can a constructor be overridden?</strong></h3>
<p>No.<br />Constructors are <strong>not inherited</strong>, so overriding doesn’t apply.</p>
<p>However, constructors can be <strong>overloaded</strong> — a class can have multiple constructors with different parameter lists.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    Person() {}
    Person(String name) {}
}
</code></pre>
<h3 id="heading-8-why-use-interfaces-instead-of-abstract-classes"><strong>8. Why use interfaces instead of abstract classes?</strong></h3>
<p>Interfaces are preferred when you want to <strong>define a contract</strong> that multiple unrelated classes can implement.</p>
<p><strong>Key reasons:</strong></p>
<ul>
<li><p>Java supports <strong>multiple interface inheritance</strong>, but not multiple class inheritance.</p>
</li>
<li><p>Promotes <strong>loose coupling</strong> — implementation can vary independently.</p>
</li>
<li><p>Ideal for defining <strong>APIs, services, or capabilities</strong> (e.g., <code>Comparable</code>, <code>Runnable</code>).</p>
</li>
</ul>
<p><strong>Example:</strong><br />A class can <code>implements Serializable, Comparable</code> but can only <code>extends</code> one abstract class.</p>
<h3 id="heading-9-interface-vs-abstract-class"><strong>9. Interface vs Abstract Class</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Interface</strong></td><td><strong>Abstract Class</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Inheritance</strong></td><td>Multiple allowed</td><td>Single allowed</td></tr>
<tr>
<td><strong>Contains</strong></td><td>Abstract methods + constants (Java 8+: default &amp; static methods too)</td><td>Can have abstract &amp; concrete methods</td></tr>
<tr>
<td><strong>Variables</strong></td><td><code>public static final</code> by default</td><td>Can be instance variables</td></tr>
<tr>
<td><strong>Constructor</strong></td><td>Not allowed</td><td>Allowed</td></tr>
<tr>
<td><strong>Use Case</strong></td><td>When defining behavior/contract</td><td>When defining base class with partial implementation</td></tr>
</tbody>
</table>
</div><p>In modern Java, interfaces are often used to define <strong>capabilities</strong>, while abstract classes define <strong>common base logic</strong>.</p>
<h3 id="heading-10-can-we-create-an-object-of-abstract-class-or-interface"><strong>10. Can we create an object of abstract class or interface?</strong></h3>
<p>No, both <strong>cannot be instantiated</strong> directly.<br />They serve as blueprints for subclasses or implementing classes.</p>
<p>However, you can create:</p>
<ul>
<li><strong>Anonymous inner classes</strong> or <strong>lambda expressions</strong> that provide concrete implementations.</li>
</ul>
<pre><code class="lang-java">Runnable r = <span class="hljs-keyword">new</span> Runnable() {
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Running..."</span>); }
};
</code></pre>
<p>Here, an <strong>anonymous implementation</strong> of the interface is created.</p>
<h2 id="heading-java-basics">Java Basics</h2>
<h3 id="heading-1-what-is-the-java-virtual-machine-jvm"><strong>1. What is the Java Virtual Machine (JVM)?</strong></h3>
<p>The <strong>JVM (Java Virtual Machine)</strong> is an abstract machine that executes Java bytecode.<br />It provides a <strong>runtime environment</strong> for Java applications and is platform-dependent.</p>
<p><strong>Key responsibilities:</strong></p>
<ul>
<li><p><strong>Loading</strong>: Uses the ClassLoader to load class files.</p>
</li>
<li><p><strong>Verifying</strong>: Ensures bytecode security.</p>
</li>
<li><p><strong>Executing</strong>: Uses the Just-In-Time (JIT) compiler to convert bytecode to native code.</p>
</li>
<li><p><strong>Memory Management</strong>: Allocates and manages heap, stack, and garbage collection.</p>
</li>
</ul>
<p>In short:<br />👉 <strong>Java code → compiled to bytecode → executed by JVM → runs on any OS (platform independence).</strong></p>
<h3 id="heading-2-explain-jre-vs-jdk-vs-jvm"><strong>2. Explain JRE vs JDK vs JVM.</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Component</strong></td><td><strong>Full Form</strong></td><td><strong>Purpose</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>JVM</strong></td><td>Java Virtual Machine</td><td>Executes Java bytecode</td></tr>
<tr>
<td><strong>JRE</strong></td><td>Java Runtime Environment</td><td>Contains JVM + libraries required to run Java apps</td></tr>
<tr>
<td><strong>JDK</strong></td><td>Java Development Kit</td><td>Contains JRE + development tools (compiler, debugger, etc.)</td></tr>
</tbody>
</table>
</div><p><strong>Relationship:</strong><br />👉 <strong>JDK = JRE + development tools</strong><br />👉 <strong>JRE = JVM + libraries</strong></p>
<h3 id="heading-3-what-is-the-role-of-main-method-in-java"><strong>3. What is the role of main() method in Java?</strong></h3>
<p><code>main()</code> is the <strong>entry point</strong> of any standalone Java application.<br />Signature:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span></span>
</code></pre>
<p><strong>Breakdown:</strong></p>
<ul>
<li><p><code>public</code>: Accessible by JVM.</p>
</li>
<li><p><code>static</code>: JVM can call it without creating an object.</p>
</li>
<li><p><code>void</code>: Doesn’t return any value.</p>
</li>
<li><p><code>String[] args</code>: Accepts command-line arguments.</p>
</li>
</ul>
<p>Without <code>main()</code>, the program doesn’t have a starting point.</p>
<h3 id="heading-4-what-happens-if-the-main-method-is-not-static"><strong>4. What happens if the main() method is not static?</strong></h3>
<p>If <code>main()</code> is <strong>not static</strong>, the JVM cannot invoke it directly because no object of the class exists yet.<br />This leads to a <strong>runtime error</strong> like:</p>
<pre><code class="lang-java">Error: Main method is not <span class="hljs-keyword">static</span> in <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainClass</span></span>
</code></pre>
<p>JVM needs <code>main()</code> to be static so that it can call it <strong>without object instantiation</strong>.</p>
<h3 id="heading-5-can-java-run-without-main"><strong>5. Can Java run without main()?</strong></h3>
<p>In modern Java (Java 7+), <strong>no</strong> — every standalone program needs a <code>main()</code> method.</p>
<p>Earlier (in applets or servlet containers), Java classes could be run without <code>main()</code> because:</p>
<ul>
<li><p>Applets start with the <code>init()</code> method.</p>
</li>
<li><p>Servlets are loaded and managed by a container (<code>init()</code>, <code>service()</code>, <code>destroy()</code>).</p>
</li>
</ul>
<p>For normal console applications → <strong>main() is mandatory</strong>.</p>
<h2 id="heading-memory-management">Memory Management</h2>
<h3 id="heading-1-explain-java-memory-model"><strong>1. Explain Java memory model.</strong></h3>
<p>The <strong>Java Memory Model (JMM)</strong> defines how Java threads interact through memory — how variables are read/written, and how visibility is ensured in concurrent execution.</p>
<p>It divides memory into:</p>
<ul>
<li><p><strong>Heap:</strong> Stores objects and their instance variables (shared across threads).</p>
</li>
<li><p><strong>Stack:</strong> Each thread has its own stack storing method calls and local variables.</p>
</li>
<li><p><strong>Method Area (Metaspace in Java 8+):</strong> Stores class-level metadata like method definitions and constant pool.</p>
</li>
<li><p><strong>PC Register:</strong> Holds address of current executing instruction.</p>
</li>
<li><p><strong>Native Method Stack:</strong> Used for native (non-Java) code execution.</p>
</li>
</ul>
<p>The JMM ensures <strong>visibility</strong>, <strong>ordering</strong>, and <strong>atomicity</strong> across threads using keywords like <code>volatile</code>, <code>synchronized</code>, and <code>final</code>.</p>
<h3 id="heading-2-what-is-heap-vs-stack"><strong>2. What is heap vs stack?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>Heap</strong></td><td><strong>Stack</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Stores</strong></td><td>Objects, instance variables</td><td>Local variables, method calls</td></tr>
<tr>
<td><strong>Shared?</strong></td><td>Shared among all threads</td><td>Each thread has its own stack</td></tr>
<tr>
<td><strong>Lifetime</strong></td><td>Exists until object is garbage collected</td><td>Exists until method completes</td></tr>
<tr>
<td><strong>Managed By</strong></td><td>Garbage Collector</td><td>JVM automatically manages</td></tr>
<tr>
<td><strong>Access Speed</strong></td><td>Slower</td><td>Faster</td></tr>
</tbody>
</table>
</div><p>Example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> x = <span class="hljs-number">10</span>;            <span class="hljs-comment">// stored in stack</span>
Person p = <span class="hljs-keyword">new</span> Person(); <span class="hljs-comment">// object p in heap, reference in stack</span>
</code></pre>
<h3 id="heading-3-what-is-permgen-and-metaspace"><strong>3. What is PermGen and Metaspace?</strong></h3>
<ul>
<li><p><strong>PermGen (Permanent Generation):</strong><br />  Used before Java 8 to store class metadata, static variables, and interned strings.<br />  Had a <strong>fixed size</strong>, which could cause <code>OutOfMemoryError: PermGen space</code>.</p>
</li>
<li><p><strong>Metaspace (Java 8+):</strong><br />  Replaced PermGen. It stores <strong>class metadata</strong> in <strong>native memory</strong> (not heap).<br />  Grows dynamically as needed, reducing memory errors.</p>
</li>
</ul>
<p>✅ <strong>In short:</strong> Metaspace is a more flexible, dynamic replacement for PermGen.</p>
<h3 id="heading-4-what-is-garbage-collection-how-does-it-work"><strong>4. What is garbage collection? How does it work?</strong></h3>
<p><strong>Garbage Collection (GC)</strong> is an automatic memory management process that reclaims memory from objects no longer reachable by any reference.</p>
<p><strong>How it works:</strong></p>
<ol>
<li><p>JVM identifies <strong>unreachable objects</strong> (not referenced anywhere).</p>
</li>
<li><p>GC frees that memory space.</p>
</li>
<li><p>Memory is reused for new objects.</p>
</li>
</ol>
<p><strong>GC Algorithms:</strong></p>
<ul>
<li><p><strong>Serial GC</strong> (single-threaded, small apps)</p>
</li>
<li><p><strong>Parallel GC</strong> (multi-threaded)</p>
</li>
<li><p><strong>G1 GC (Garbage First)</strong> – default in Java 9+, low pause time collector.</p>
</li>
</ul>
<p><strong>Phases:</strong></p>
<ul>
<li><p><strong>Mark:</strong> Identify live objects.</p>
</li>
<li><p><strong>Sweep/Compact:</strong> Remove dead objects and defragment memory.</p>
</li>
</ul>
<p>Developers can trigger GC via <code>System.gc()</code>, but JVM decides the actual execution time.</p>
<h3 id="heading-5-finalize-method-how-and-when-is-it-called"><strong>5. Finalize method – how and when is it called?</strong></h3>
<p><code>finalize()</code> is a method defined in the <code>Object</code> class:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">finalize</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Throwable</span>
</code></pre>
<p>It’s called by the <strong>Garbage Collector</strong> before reclaiming an object’s memory — a last chance to release resources.</p>
<p><strong>However:</strong></p>
<ul>
<li><p>Execution is <strong>not guaranteed</strong> or <strong>timely</strong>.</p>
</li>
<li><p>It might <strong>never be called</strong> if the program exits before GC runs.</p>
</li>
</ul>
<p>✅ Since Java 9, <code>finalize()</code> is <strong>deprecated</strong>.<br />Modern alternatives:</p>
<ul>
<li><p>Use <code>try-with-resources</code> for closing streams.</p>
</li>
<li><p>Implement <code>AutoCloseable</code> for cleanup logic.</p>
</li>
</ul>
<h2 id="heading-access-modifiers">Access Modifiers</h2>
<h3 id="heading-1-difference-between-private-protected-public-and-default"><strong>1. Difference between private, protected, public, and default</strong></h3>
<p>Java provides four access levels to control visibility of classes, methods, and variables.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Modifier</strong></td><td><strong>Within Class</strong></td><td><strong>Within Package</strong></td><td><strong>Subclass (Other Package)</strong></td><td><strong>Outside Package</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>private</strong></td><td>✅</td><td>❌</td><td>❌</td><td>❌</td></tr>
<tr>
<td><strong>default</strong> <em>(no modifier)</em></td><td>✅</td><td>✅</td><td>❌</td><td>❌</td></tr>
<tr>
<td><strong>protected</strong></td><td>✅</td><td>✅</td><td>✅</td><td>❌</td></tr>
<tr>
<td><strong>public</strong></td><td>✅</td><td>✅</td><td>✅</td><td>✅</td></tr>
</tbody>
</table>
</div><p><strong>Summary:</strong></p>
<ul>
<li><p><strong>private</strong> → Most restrictive; used for encapsulation.</p>
</li>
<li><p><strong>default</strong> → Accessible within the same package.</p>
</li>
<li><p><strong>protected</strong> → Visible to subclasses even if they’re in different packages.</p>
</li>
<li><p><strong>public</strong> → Accessible from anywhere.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">protected</span> String name;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">greet</span><span class="hljs-params">()</span> </span>{}
}
</code></pre>
<h3 id="heading-2-can-a-class-be-private-in-java"><strong>2. Can a class be private in Java?</strong></h3>
<p>Top-level (outer) classes <strong>cannot be private</strong> — they must be either <strong>public</strong> or <strong>default</strong>.</p>
<p>However, <strong>inner classes</strong> can be private.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Outer</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Inner</span> </span>{   <span class="hljs-comment">// ✅ allowed</span>
        <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Inner"</span>); }
    }
}
</code></pre>
<p>If a top-level class were private, <strong>no other class</strong> (even in the same package) could access it — defeating the purpose of reusability.</p>
<h3 id="heading-3-what-are-static-blocks"><strong>3. What are static blocks?</strong></h3>
<p>A <strong>static block</strong> in Java is used for <strong>class-level initialization</strong>.<br />It runs <strong>once</strong>, when the class is <strong>first loaded</strong> into memory (before any constructor or object creation).</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DatabaseConnection</span> </span>{
    <span class="hljs-keyword">static</span> {
        System.out.println(<span class="hljs-string">"Initializing DB connection..."</span>);
    }
}
</code></pre>
<p><strong>Use cases:</strong></p>
<ul>
<li><p>Initialize static variables.</p>
</li>
<li><p>Load configurations.</p>
</li>
<li><p>Perform one-time setup (e.g., registering JDBC drivers).</p>
</li>
</ul>
<p><strong>Order of execution:</strong></p>
<ol>
<li><p>Static variables.</p>
</li>
<li><p>Static blocks (in order of appearance).</p>
</li>
<li><p>Constructors (when object is created).</p>
</li>
</ol>
<h2 id="heading-exception-handling">Exception Handling</h2>
<h3 id="heading-1-checked-vs-unchecked-exceptions"><strong>1. Checked vs Unchecked Exceptions?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Type</strong></td><td><strong>Checked Exception</strong></td><td><strong>Unchecked Exception</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Inheritance</strong></td><td>Subclass of <code>Exception</code> (excluding <code>RuntimeException</code>)</td><td>Subclass of <code>RuntimeException</code></td></tr>
<tr>
<td><strong>Checked at</strong></td><td>Compile-time</td><td>Runtime</td></tr>
<tr>
<td><strong>Handling Required?</strong></td><td>Must be handled or declared using <code>throws</code></td><td>Optional</td></tr>
<tr>
<td><strong>Examples</strong></td><td><code>IOException</code>, <code>SQLException</code>, <code>FileNotFoundException</code></td><td><code>NullPointerException</code>, <code>ArithmeticException</code>, <code>ArrayIndexOutOfBoundsException</code></td></tr>
</tbody>
</table>
</div><p><strong>Key point:</strong><br />Checked exceptions represent <strong>recoverable errors</strong>, while unchecked ones indicate <strong>programming bugs</strong> (e.g., null access).</p>
<h3 id="heading-2-difference-between-throw-and-throws"><strong>2. Difference between throw and throws?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Keyword</strong></td><td><code>throw</code></td><td><code>throws</code></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Purpose</strong></td><td>Used to actually throw an exception</td><td>Declares that a method may throw exceptions</td></tr>
<tr>
<td><strong>Usage Place</strong></td><td>Inside method body</td><td>In method signature</td></tr>
<tr>
<td><strong>Follows</strong></td><td>Single exception instance</td><td>One or more exception classes</td></tr>
<tr>
<td><strong>Example</strong></td><td><code>throw new IOException("File not found");</code></td><td><code>void readFile() throws IOException {}</code></td></tr>
</tbody>
</table>
</div><p>Example:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">readFile</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException </span>{
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IOException(<span class="hljs-string">"Error reading file"</span>);
}
</code></pre>
<h3 id="heading-3-can-we-have-try-block-without-catchfinally"><strong>3. Can we have try block without catch/finally?</strong></h3>
<p>No ❌<br />A <code>try</code> block must be followed by at least <strong>one</strong> of the following:</p>
<ul>
<li><p>A <code>catch</code> block</p>
</li>
<li><p>A <code>finally</code> block</p>
</li>
</ul>
<p>However, <code>try-finally</code> without <code>catch</code> is valid:</p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    System.out.println(<span class="hljs-string">"Try block"</span>);
} <span class="hljs-keyword">finally</span> {
    System.out.println(<span class="hljs-string">"Cleanup code"</span>);
}
</code></pre>
<p>This ensures cleanup executes even if no exception occurs.</p>
<h3 id="heading-4-what-is-the-use-of-finally-block"><strong>4. What is the use of finally block?</strong></h3>
<p>The <code>finally</code> block is used for <strong>resource cleanup</strong> — it executes <strong>always</strong>, regardless of whether an exception occurs or not.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    FileInputStream fis = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">"data.txt"</span>);
} <span class="hljs-keyword">catch</span> (IOException e) {
    e.printStackTrace();
} <span class="hljs-keyword">finally</span> {
    System.out.println(<span class="hljs-string">"Closing resources..."</span>);
}
</code></pre>
<p>✅ Executed:</p>
<ul>
<li><p>After try or catch block</p>
</li>
<li><p>Even if <code>return</code> is used inside try or catch<br />  ❌ Not executed if JVM exits via <code>System.exit(0)</code> or power failure.</p>
</li>
</ul>
<p><strong>Modern alternative:</strong><br />Use <strong>try-with-resources (Java 7+)</strong> to auto-close resources.</p>
<h3 id="heading-5-custom-exception-in-java"><strong>5. Custom exception in Java?</strong></h3>
<p>A <strong>custom exception</strong> allows developers to define domain-specific error types.</p>
<p><strong>Steps to create:</strong></p>
<ol>
<li><p>Extend <code>Exception</code> (for checked) or <code>RuntimeException</code> (for unchecked).</p>
</li>
<li><p>Add constructors for custom messages.</p>
</li>
</ol>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvalidAgeException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvalidAgeException</span><span class="hljs-params">(String msg)</span> </span>{
        <span class="hljs-keyword">super</span>(msg);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Validator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">validate</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> <span class="hljs-keyword">throws</span> InvalidAgeException </span>{
        <span class="hljs-keyword">if</span> (age &lt; <span class="hljs-number">18</span>)
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidAgeException(<span class="hljs-string">"Age must be &gt;= 18"</span>);
    }
}
</code></pre>
<p><strong>Use cases:</strong></p>
<ul>
<li><p>Validation (e.g., invalid user input)</p>
</li>
<li><p>Business logic constraints</p>
</li>
<li><p>Domain-specific error reporting (e.g., <code>InsufficientBalanceException</code>)</p>
</li>
</ul>
<h2 id="heading-collections-framework">Collections Framework</h2>
<h3 id="heading-1-list-vs-set-vs-map"><strong>1. List vs Set vs Map?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>List</strong></td><td><strong>Set</strong></td><td><strong>Map</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Stores</strong></td><td>Ordered collection of elements</td><td>Unique elements (no duplicates)</td><td>Key-value pairs</td></tr>
<tr>
<td><strong>Duplicates</strong></td><td>Allowed</td><td>Not allowed</td><td>Keys: not allowed, Values: allowed</td></tr>
<tr>
<td><strong>Order</strong></td><td>Maintains insertion order</td><td>Depends on implementation</td><td>Depends on implementation</td></tr>
<tr>
<td><strong>Implementations</strong></td><td><code>ArrayList</code>, <code>LinkedList</code>, <code>Vector</code></td><td><code>HashSet</code>, <code>LinkedHashSet</code>, <code>TreeSet</code></td><td><code>HashMap</code>, <code>TreeMap</code>, <code>LinkedHashMap</code></td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<pre><code class="lang-java">List&lt;String&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
Set&lt;String&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
Map&lt;Integer, String&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
</code></pre>
<h3 id="heading-2-arraylist-vs-linkedlist"><strong>2. ArrayList vs LinkedList?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Aspect</td><td>ArrayList</td><td>LinkedList</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Data Structure</strong></td><td>Dynamic array</td><td>Doubly linked list</td></tr>
<tr>
<td><strong>Access Time</strong></td><td>O(1) for index-based access</td><td>O(n) traversal required</td></tr>
<tr>
<td><strong>Insertion/Deletion (middle)</strong></td><td>O(n)</td><td>O(1) if node reference known</td></tr>
<tr>
<td><strong>Memory Usage</strong></td><td>Less (compact)</td><td>More (extra node references)</td></tr>
<tr>
<td><strong>Use Case</strong></td><td>Random access</td><td>Frequent insertions/deletions</td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<ul>
<li><p>Use <code>ArrayList</code> when reads are frequent.</p>
</li>
<li><p>Use <code>LinkedList</code> when insertions/removals are frequent.</p>
</li>
</ul>
<h3 id="heading-3-hashmap-vs-hashtable"><strong>3. HashMap vs Hashtable?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>HashMap</strong></td><td><strong>Hashtable</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Thread-Safety</strong></td><td>Not synchronized</td><td>Synchronized</td></tr>
<tr>
<td><strong>Null Keys/Values</strong></td><td>Allows one null key, multiple null values</td><td>Doesn’t allow nulls</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Faster (no locking)</td><td>Slower (locks entire table)</td></tr>
<tr>
<td><strong>Introduced In</strong></td><td>Java 1.2</td><td>Java 1.0</td></tr>
<tr>
<td><strong>Preferred?</strong></td><td>Yes, in modern Java</td><td>Legacy class</td></tr>
</tbody>
</table>
</div><p>✅ For thread-safe alternatives, use <code>ConcurrentHashMap</code> instead of <code>Hashtable</code>.</p>
<h3 id="heading-4-how-does-hashmap-work-internally"><strong>4. How does HashMap work internally?</strong></h3>
<p>HashMap stores data in <strong>buckets</strong> using a <strong>hashing mechanism</strong>.</p>
<p><strong>Process:</strong></p>
<ol>
<li><p>Key’s <code>hashCode()</code> is computed.</p>
</li>
<li><p>The hash is mapped to an index in the bucket array (<code>(n - 1) &amp; hash</code>).</p>
</li>
<li><p>Each bucket holds a linked list or tree (Java 8+).</p>
</li>
<li><p>On <code>put()</code>:</p>
<ul>
<li><p>If key exists → value replaced.</p>
</li>
<li><p>If not → new node added.</p>
</li>
</ul>
</li>
<li><p>On <code>get()</code>:</p>
<ul>
<li>Hash computed → bucket located → key compared using <code>equals()</code>.</li>
</ul>
</li>
</ol>
<p><strong>Optimization (Java 8+):</strong></p>
<ul>
<li>If bucket size &gt; 8, converts linked list → <strong>balanced tree</strong> (Red-Black Tree) for O(log n) lookup.</li>
</ul>
<h3 id="heading-5-what-is-the-load-factor-and-threshold-in-hashmap"><strong>5. What is the load factor and threshold in HashMap?</strong></h3>
<ul>
<li><p><strong>Load Factor:</strong> Defines how full the HashMap can get before resizing (default = 0.75).</p>
</li>
<li><p><strong>Threshold:</strong> <code>capacity × loadFactor</code>.<br />  When the number of entries exceeds this threshold, HashMap <strong>resizes</strong> (doubles its capacity).</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-java">HashMap&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;(<span class="hljs-number">16</span>, <span class="hljs-number">0.75f</span>);
</code></pre>
<p>✅ Resizing improves performance but comes with a cost — it’s best to initialize maps with an estimated size to minimize rehashing.</p>
<h3 id="heading-6-what-are-fail-fast-and-fail-safe-iterators"><strong>6. What are fail-fast and fail-safe iterators?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Type</strong></td><td><strong>Behavior</strong></td><td><strong>Example Collections</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Fail-Fast</strong></td><td>Throws <code>ConcurrentModificationException</code> if the collection is modified while iterating</td><td><code>ArrayList</code>, <code>HashMap</code></td></tr>
<tr>
<td><strong>Fail-Safe</strong></td><td>Works on a clone or snapshot of the collection</td><td><code>ConcurrentHashMap</code>, <code>CopyOnWriteArrayList</code></td></tr>
</tbody>
</table>
</div><p>Example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (Integer i : list) {
    list.add(<span class="hljs-number">10</span>); <span class="hljs-comment">// ❌ throws ConcurrentModificationException</span>
}
</code></pre>
<p>✅ Use <strong>fail-safe</strong> collections in concurrent environments.</p>
<h3 id="heading-7-what-is-concurrenthashmap-and-how-is-it-different"><strong>7. What is ConcurrentHashMap and how is it different?</strong></h3>
<p><code>ConcurrentHashMap</code> is a thread-safe alternative to <code>HashMap</code> that provides <strong>high concurrency</strong> with minimal locking.</p>
<p><strong>How it differs:</strong></p>
<ul>
<li><p>No full-table lock (uses <strong>segment-level locking</strong> or <strong>CAS</strong> in Java 8+).</p>
</li>
<li><p>Null keys/values are <strong>not allowed</strong>.</p>
</li>
<li><p>Iterators are <strong>fail-safe</strong> (operate on snapshot).</p>
</li>
<li><p>Performs better than <code>Hashtable</code> under multithreading.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">ConcurrentHashMap&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> ConcurrentHashMap&lt;&gt;();
map.put(<span class="hljs-string">"A"</span>, <span class="hljs-number">1</span>);
</code></pre>
<h3 id="heading-8-treemap-vs-hashmap"><strong>8. TreeMap vs HashMap?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>HashMap</td><td>TreeMap</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Order</strong></td><td>No ordering</td><td>Sorted (natural/comparator)</td></tr>
<tr>
<td><strong>Implementation</strong></td><td>Hash table</td><td>Red-Black tree</td></tr>
<tr>
<td><strong>Null Keys</strong></td><td>Allows one</td><td>Doesn’t allow null key</td></tr>
<tr>
<td><strong>Performance</strong></td><td>O(1) average</td><td>O(log n)</td></tr>
<tr>
<td><strong>Use Case</strong></td><td>Fast lookups</td><td>Sorted data retrieval</td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<pre><code class="lang-java">Map&lt;Integer, String&gt; map = <span class="hljs-keyword">new</span> TreeMap&lt;&gt;();
map.put(<span class="hljs-number">2</span>, <span class="hljs-string">"B"</span>);
map.put(<span class="hljs-number">1</span>, <span class="hljs-string">"A"</span>); <span class="hljs-comment">// Automatically sorted by key</span>
</code></pre>
<h3 id="heading-9-what-is-linkedhashmap"><strong>9. What is LinkedHashMap?</strong></h3>
<p><code>LinkedHashMap</code> maintains <strong>insertion order</strong> or <strong>access order</strong> of entries.</p>
<p><strong>Internally:</strong><br />It extends <code>HashMap</code> and adds a <strong>doubly-linked list</strong> to preserve order.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Map&lt;Integer, String&gt; map = <span class="hljs-keyword">new</span> LinkedHashMap&lt;&gt;();
map.put(<span class="hljs-number">1</span>, <span class="hljs-string">"A"</span>);
map.put(<span class="hljs-number">2</span>, <span class="hljs-string">"B"</span>);
</code></pre>
<p>✅ Useful when you need predictable iteration order or LRU caching (using <code>removeEldestEntry</code>).</p>
<h3 id="heading-10-when-to-use-arraylist-vs-vector"><strong>10. When to use ArrayList vs Vector?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>ArrayList</strong></td><td><strong>Vector</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Synchronization</strong></td><td>Not synchronized</td><td>Synchronized</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Faster</td><td>Slower (locks every method)</td></tr>
<tr>
<td><strong>Introduced In</strong></td><td>Java 1.2</td><td>Java 1.0 (legacy)</td></tr>
<tr>
<td><strong>Growth</strong></td><td>Grows by 50%</td><td>Grows by 100% (doubles)</td></tr>
</tbody>
</table>
</div><p>✅ Modern Java avoids <code>Vector</code>.<br />Use <code>ArrayList</code> for single-threaded cases, or <code>Collections.synchronizedList()</code> if synchronization is needed.</p>
<h2 id="heading-multithreading-and-concurrency">Multithreading and Concurrency</h2>
<h3 id="heading-1-difference-between-process-and-thread"><strong>1. Difference between process and thread?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Process</strong></td><td><strong>Thread</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Definition</strong></td><td>Independent program in execution</td><td>Smallest unit of a process</td></tr>
<tr>
<td><strong>Memory</strong></td><td>Has its own memory space</td><td>Shares memory with other threads of same process</td></tr>
<tr>
<td><strong>Communication</strong></td><td>Inter-process communication is complex</td><td>Easier via shared objects</td></tr>
<tr>
<td><strong>Failure Impact</strong></td><td>One process crash doesn’t affect others</td><td>Thread crash may affect whole process</td></tr>
<tr>
<td><strong>Example</strong></td><td>Running two Java programs</td><td>Two threads in same Java program</td></tr>
</tbody>
</table>
</div><p><strong>In short:</strong> Threads share the same heap, enabling lightweight multitasking within a single process.</p>
<h3 id="heading-2-ways-to-create-a-thread-in-java"><strong>2. Ways to create a thread in Java?</strong></h3>
<p>There are <strong>three main ways</strong>:</p>
<ol>
<li><p><strong>Extend</strong> <code>Thread</code> class</p>
<pre><code class="lang-java"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyThread</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Thread</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
         System.out.println(<span class="hljs-string">"Thread running..."</span>);
     }
 }
 <span class="hljs-keyword">new</span> MyThread().start();
</code></pre>
</li>
<li><p><strong>Implement</strong> <code>Runnable</code> interface</p>
<pre><code class="lang-java"> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyTask</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Runnable</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
         System.out.println(<span class="hljs-string">"Running via Runnable"</span>);
     }
 }
 <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> MyTask()).start();
</code></pre>
</li>
<li><p><strong>Use</strong> <code>ExecutorService</code> or <code>Callable</code> (preferred in modern Java)</p>
<pre><code class="lang-java"> ExecutorService service = Executors.newFixedThreadPool(<span class="hljs-number">2</span>);
 service.submit(() -&gt; System.out.println(<span class="hljs-string">"Running in pool"</span>));
</code></pre>
</li>
</ol>
<p>✅ Best practice: Use <code>ExecutorService</code> to manage threads efficiently.</p>
<h3 id="heading-3-thread-vs-runnable"><strong>3. Thread vs Runnable?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><strong>Thread</strong></td><td><strong>Runnable</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Inheritance</strong></td><td>Requires extending Thread</td><td>Can be implemented along with other interfaces</td></tr>
<tr>
<td><strong>Code Reuse</strong></td><td>Less flexible</td><td>More flexible (no multiple inheritance issue)</td></tr>
<tr>
<td><strong>Preferred</strong></td><td>For small/simple use</td><td>Runnable preferred for real-world apps</td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong><br />If your class already extends another class, use <code>Runnable</code> since Java doesn’t support multiple inheritance.</p>
<h3 id="heading-4-what-is-thread-lifecycle"><strong>4. What is thread lifecycle?</strong></h3>
<p>A thread in Java passes through these <strong>five states</strong>:</p>
<ol>
<li><p><strong>New</strong> – Created but not started (<code>new Thread()</code>).</p>
</li>
<li><p><strong>Runnable</strong> – Ready to run, waiting for CPU (<code>start()</code> called).</p>
</li>
<li><p><strong>Running</strong> – Currently executing.</p>
</li>
<li><p><strong>Blocked/Waiting</strong> – Waiting for a resource or another thread.</p>
</li>
<li><p><strong>Terminated</strong> – Execution completed or stopped.</p>
</li>
</ol>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Thread t = <span class="hljs-keyword">new</span> Thread(() -&gt; {});
t.start();  <span class="hljs-comment">// Runnable</span>
</code></pre>
<h3 id="heading-5-difference-between-wait-sleep-join"><strong>5. Difference between wait, sleep, join?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Method</strong></td><td><strong>Defined In</strong></td><td><strong>Releases Lock?</strong></td><td><strong>Purpose</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>wait()</strong></td><td>Object class</td><td>✅ Yes</td><td>Waits until notified (<code>notify()</code> / <code>notifyAll()</code>)</td></tr>
<tr>
<td><strong>sleep()</strong></td><td>Thread class</td><td>❌ No</td><td>Pauses execution for given time</td></tr>
<tr>
<td><strong>join()</strong></td><td>Thread class</td><td>❌ No</td><td>Waits for another thread to finish</td></tr>
</tbody>
</table>
</div><p>Example:</p>
<pre><code class="lang-java">Thread t = <span class="hljs-keyword">new</span> Thread(() -&gt; System.out.println(<span class="hljs-string">"Task"</span>));
t.start();
t.join(); <span class="hljs-comment">// waits for t to finish</span>
</code></pre>
<h3 id="heading-6-what-is-synchronized-blockmethod"><strong>6. What is synchronized block/method?</strong></h3>
<p>The <code>synchronized</code> keyword ensures <strong>mutual exclusion</strong> — only one thread can access a block/method at a time for a given object.</p>
<p><strong>Types:</strong></p>
<ul>
<li><p><strong>Synchronized method</strong></p>
<pre><code class="lang-java">  <span class="hljs-function"><span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">increment</span><span class="hljs-params">()</span> </span>{ 
      count++; 
  }
</code></pre>
</li>
<li><p><strong>Synchronized block</strong></p>
<pre><code class="lang-java">  <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">increment</span><span class="hljs-params">()</span> </span>{
      <span class="hljs-keyword">synchronized</span>(<span class="hljs-keyword">this</span>) {
          count++;
      }
  }
</code></pre>
</li>
</ul>
<p><strong>Benefits:</strong> Prevents race conditions.<br /><strong>Downside:</strong> Can reduce performance due to locking.</p>
<h3 id="heading-7-what-is-a-deadlock-how-to-prevent-it"><strong>7. What is a deadlock? How to prevent it?</strong></h3>
<p>A <strong>deadlock</strong> occurs when two or more threads are waiting for each other’s locks indefinitely.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">synchronized</span> (obj1) {
    <span class="hljs-keyword">synchronized</span> (obj2) { ... }
}
</code></pre>
<p>Another thread might lock <code>obj2</code> first, then wait for <code>obj1</code>.</p>
<p><strong>Prevention:</strong></p>
<ul>
<li><p>Acquire locks in a consistent order.</p>
</li>
<li><p>Use <code>tryLock()</code> with timeout (<code>ReentrantLock</code>).</p>
</li>
<li><p>Avoid nested locks where possible.</p>
</li>
</ul>
<h3 id="heading-8-what-is-volatile-keyword"><strong>8. What is volatile keyword?</strong></h3>
<p>The <code>volatile</code> keyword ensures that a variable’s value is <strong>always read from main memory</strong>, not from a thread’s local cache.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">volatile</span> <span class="hljs-keyword">boolean</span> flag = <span class="hljs-keyword">true</span>;
</code></pre>
<p>If one thread changes <code>flag</code>, other threads immediately see the updated value.</p>
<p><strong>Important:</strong></p>
<ul>
<li><p>Ensures <strong>visibility</strong>, not <strong>atomicity</strong>.</p>
</li>
<li><p>For compound operations (e.g., <code>count++</code>), use synchronization or <code>AtomicInteger</code>.</p>
</li>
</ul>
<h3 id="heading-9-difference-between-executorservice-and-thread"><strong>9. Difference between ExecutorService and Thread?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>Thread</strong></td><td><strong>ExecutorService</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Creation</strong></td><td>Manually create and start threads</td><td>Manages thread pool automatically</td></tr>
<tr>
<td><strong>Reusability</strong></td><td>One-time use</td><td>Threads are reused</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Higher overhead</td><td>More efficient for multiple tasks</td></tr>
<tr>
<td><strong>Introduced</strong></td><td>Java 1.0</td><td>Java 5 (<code>java.util.concurrent</code>)</td></tr>
</tbody>
</table>
</div><p>Example:</p>
<pre><code class="lang-java">ExecutorService executor = Executors.newFixedThreadPool(<span class="hljs-number">3</span>);
executor.submit(() -&gt; System.out.println(<span class="hljs-string">"Task executed"</span>));
executor.shutdown();
</code></pre>
<p>✅ <strong>Best practice:</strong> Always use <code>ExecutorService</code> for managing multiple threads efficiently.</p>
<h3 id="heading-10-what-is-thread-safety"><strong>10. What is thread safety?</strong></h3>
<p><strong>Thread safety</strong> means an object or code segment behaves correctly when accessed by multiple threads simultaneously.</p>
<p><strong>Ways to achieve:</strong></p>
<ul>
<li><p>Use <strong>immutable objects</strong></p>
</li>
<li><p>Use <strong>synchronized blocks</strong></p>
</li>
<li><p>Use <strong>atomic classes</strong> (<code>AtomicInteger</code>, <code>AtomicReference</code>)</p>
</li>
<li><p>Use <strong>concurrent collections</strong> (<code>ConcurrentHashMap</code>, <code>CopyOnWriteArrayList</code>)</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">AtomicInteger counter = <span class="hljs-keyword">new</span> AtomicInteger();
counter.incrementAndGet();
</code></pre>
<p>✅ Thread-safe code avoids <strong>race conditions</strong> and <strong>data inconsistency</strong>.</p>
<h2 id="heading-java-8-features">Java 8 Features</h2>
<h3 id="heading-1-what-are-the-major-features-introduced-in-java-8"><strong>1. What are the major features introduced in Java 8?</strong></h3>
<p>Java 8 introduced <strong>functional programming</strong> concepts and several performance improvements.</p>
<p><strong>Key Features:</strong></p>
<ul>
<li><p>Lambda Expressions</p>
</li>
<li><p>Functional Interfaces</p>
</li>
<li><p>Stream API</p>
</li>
<li><p>Optional class</p>
</li>
<li><p>Method References</p>
</li>
<li><p>Default and Static methods in Interfaces</p>
</li>
<li><p>Date and Time API (<code>java.time</code>)</p>
</li>
<li><p>Parallel Streams</p>
</li>
</ul>
<h3 id="heading-2-what-are-lambda-expressions"><strong>2. What are lambda expressions?</strong></h3>
<p>A <strong>lambda expression</strong> provides a concise way to represent anonymous functions.</p>
<p><strong>Syntax:</strong></p>
<pre><code class="lang-java">(parameter) -&gt; expression
</code></pre>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">List&lt;String&gt; names = Arrays.asList(<span class="hljs-string">"John"</span>, <span class="hljs-string">"Jane"</span>, <span class="hljs-string">"Max"</span>);
names.forEach(name -&gt; System.out.println(name));
</code></pre>
<p><strong>Before Java 8:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (String name : names)
    System.out.println(name);
</code></pre>
<p>✅ <strong>Advantages:</strong></p>
<ul>
<li><p>Reduces boilerplate code</p>
</li>
<li><p>Enables functional programming</p>
</li>
<li><p>Works well with Streams and Collections</p>
</li>
</ul>
<h3 id="heading-3-what-is-a-functional-interface"><strong>3. What is a functional interface?</strong></h3>
<p>A <strong>functional interface</strong> is an interface that contains exactly <strong>one abstract method</strong>.<br />It can have <strong>default or static methods</strong> as well.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-meta">@FunctionalInterface</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span></span>;
}
</code></pre>
<p><strong>Built-in Functional Interfaces (in</strong> <code>java.util.function</code>):</p>
<ul>
<li><p><code>Predicate&lt;T&gt;</code> → returns boolean</p>
</li>
<li><p><code>Function&lt;T, R&gt;</code> → transforms T to R</p>
</li>
<li><p><code>Consumer&lt;T&gt;</code> → accepts and performs action</p>
</li>
<li><p><code>Supplier&lt;T&gt;</code> → returns value without input</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Predicate&lt;Integer&gt; isEven = x -&gt; x % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>;
System.out.println(isEven.test(<span class="hljs-number">4</span>)); <span class="hljs-comment">// true</span>
</code></pre>
<h3 id="heading-4-what-is-the-stream-api"><strong>4. What is the Stream API?</strong></h3>
<p>The <strong>Stream API</strong> is used to process collections of data in a <strong>declarative and functional style</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">List&lt;Integer&gt; nums = Arrays.asList(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>);
List&lt;Integer&gt; squares = nums.stream()
                            .map(n -&gt; n * n)
                            .collect(Collectors.toList());
System.out.println(squares);
</code></pre>
<p><strong>Key Operations:</strong></p>
<ul>
<li><p>Intermediate → <code>filter()</code>, <code>map()</code>, <code>sorted()</code></p>
</li>
<li><p>Terminal → <code>collect()</code>, <code>forEach()</code>, <code>count()</code>, <code>reduce()</code></p>
</li>
</ul>
<p>✅ <strong>Streams don’t modify the original collection.</strong></p>
<h3 id="heading-5-what-is-the-difference-between-map-and-flatmap"><strong>5. What is the difference between map() and flatMap()?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Method</strong></td><td><strong>Purpose</strong></td><td><strong>Example</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>map()</strong></td><td>Transforms each element</td><td><code>[1,2,3] → [1,4,9]</code></td></tr>
<tr>
<td><strong>flatMap()</strong></td><td>Flattens nested streams</td><td><code>[[1,2],[3,4]] → [1,2,3,4]</code></td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<pre><code class="lang-java">List&lt;List&lt;Integer&gt;&gt; list = Arrays.asList(Arrays.asList(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>), Arrays.asList(<span class="hljs-number">3</span>,<span class="hljs-number">4</span>));
list.stream().flatMap(Collection::stream).forEach(System.out::println);
</code></pre>
<h3 id="heading-6-what-is-the-optional-class"><strong>6. What is the Optional class?</strong></h3>
<p><code>Optional&lt;T&gt;</code> is a container that may or may not hold a non-null value.<br />It helps <strong>avoid NullPointerException</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Optional&lt;String&gt; name = Optional.ofNullable(getName());
System.out.println(name.orElse(<span class="hljs-string">"Unknown"</span>));
</code></pre>
<p><strong>Common methods:</strong></p>
<ul>
<li><p><code>isPresent()</code></p>
</li>
<li><p><code>orElse()</code></p>
</li>
<li><p><code>orElseGet()</code></p>
</li>
<li><p><code>orElseThrow()</code></p>
</li>
<li><p><code>map()</code> and <code>flatMap()</code></p>
</li>
</ul>
<p>✅ Always use <code>Optional</code> for return types, not fields.</p>
<h3 id="heading-7-what-are-method-references"><strong>7. What are method references?</strong></h3>
<p>Method references provide a shorthand for calling existing methods using <code>::</code>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">list.forEach(System.out::println);
</code></pre>
<p><strong>Types:</strong></p>
<ul>
<li><p>Static method → <code>ClassName::staticMethod</code></p>
</li>
<li><p>Instance method → <code>object::instanceMethod</code></p>
</li>
<li><p>Constructor → <code>ClassName::new</code></p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Supplier&lt;List&lt;String&gt;&gt; supplier = ArrayList::<span class="hljs-keyword">new</span>;
</code></pre>
<h3 id="heading-8-what-are-default-and-static-methods-in-interfaces"><strong>8. What are default and static methods in interfaces?</strong></h3>
<p><strong>Default methods</strong>: Provide a method body inside an interface.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">default</span> <span class="hljs-keyword">void</span> <span class="hljs-title">start</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Vehicle started"</span>);
    }
}
</code></pre>
<p><strong>Static methods</strong> in interfaces belong to the interface itself:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Utils</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Static method in interface"</span>);
    }
}
</code></pre>
<p>✅ These features were introduced to maintain backward compatibility when new methods were added to interfaces like <code>List</code> and <code>Map</code>.</p>
<h3 id="heading-9-what-is-the-new-date-and-time-api-javatime"><strong>9. What is the new Date and Time API (java.time)?</strong></h3>
<p>Java 8 introduced a <strong>modern, immutable, thread-safe</strong> Date-Time API.</p>
<p><strong>Key Classes:</strong></p>
<ul>
<li><p><code>LocalDate</code>, <code>LocalTime</code>, <code>LocalDateTime</code></p>
</li>
<li><p><code>ZonedDateTime</code></p>
</li>
<li><p><code>Period</code>, <code>Duration</code></p>
</li>
<li><p><code>DateTimeFormatter</code></p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(<span class="hljs-number">1</span>);
System.out.println(tomorrow);
</code></pre>
<p>✅ No more <code>java.util.Date</code> and <code>SimpleDateFormat</code> pain!</p>
<h3 id="heading-10-what-are-parallel-streams"><strong>10. What are parallel streams?</strong></h3>
<p>Parallel streams allow data to be processed <strong>in multiple threads automatically</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">list.parallelStream()
    .filter(x -&gt; x &gt; <span class="hljs-number">10</span>)
    .forEach(System.out::println);
</code></pre>
<p><strong>Note:</strong></p>
<ul>
<li><p>Use parallel streams <strong>for CPU-intensive</strong> operations.</p>
</li>
<li><p>Avoid for <strong>IO-bound</strong> or small datasets (due to overhead).</p>
</li>
</ul>
<h2 id="heading-strings">Strings</h2>
<h3 id="heading-1-string-vs-stringbuilder-vs-stringbuffer"><strong>1. String vs StringBuilder vs StringBuffer?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Feature</strong></td><td><code>String</code></td><td><code>StringBuilder</code></td><td><code>StringBuffer</code></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Mutability</strong></td><td>Immutable</td><td>Mutable</td><td>Mutable</td></tr>
<tr>
<td><strong>Thread-safety</strong></td><td>Not thread-safe</td><td>Not thread-safe</td><td>Thread-safe (synchronized)</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Slower (creates new objects)</td><td>Faster (no synchronization)</td><td>Slightly slower (synchronization overhead)</td></tr>
<tr>
<td><strong>Use Case</strong></td><td>When data doesn’t change</td><td>Single-threaded string manipulations</td><td>Multi-threaded string manipulations</td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<pre><code class="lang-java">String s = <span class="hljs-string">"Hello"</span>;
s.concat(<span class="hljs-string">" World"</span>); <span class="hljs-comment">// New object created</span>

StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder(<span class="hljs-string">"Hello"</span>);
sb.append(<span class="hljs-string">" World"</span>); <span class="hljs-comment">// Modified in place</span>
</code></pre>
<p>✅ For most use cases → prefer <strong>StringBuilder</strong> (fast, flexible).</p>
<h3 id="heading-2-how-are-strings-stored-in-memory"><strong>2. How are strings stored in memory?</strong></h3>
<ul>
<li><p>Strings are stored in a special area of heap memory called the <strong>String Constant Pool (SCP)</strong>.</p>
</li>
<li><p>When you create a string literal, e.g., <code>"Java"</code>, it’s <strong>interned</strong> — meaning:</p>
<ul>
<li><p>If <code>"Java"</code> already exists in the pool, the same reference is reused.</p>
</li>
<li><p>If not, it’s added to the pool.</p>
</li>
</ul>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String s1 = <span class="hljs-string">"Java"</span>;
String s2 = <span class="hljs-string">"Java"</span>;
System.out.println(s1 == s2); <span class="hljs-comment">// true (same reference)</span>
</code></pre>
<p>✅ <strong>String literals</strong> are interned;<br /><code>new String("Java")</code> creates a <strong>new object</strong> on the heap (not in SCP).</p>
<h3 id="heading-3-what-is-the-string-constant-pool"><strong>3. What is the String Constant Pool?</strong></h3>
<p>The <strong>String Constant Pool</strong> (SCP) is part of the <strong>heap memory</strong> (since Java 7+).<br />It’s a cache that stores <strong>unique string literals</strong> to improve performance and save memory.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String a = <span class="hljs-string">"Test"</span>;
String b = <span class="hljs-string">"Test"</span>;
System.out.println(a == b); <span class="hljs-comment">// true (both refer to same object)</span>
</code></pre>
<p>If created using <code>new</code>:</p>
<pre><code class="lang-java">String c = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Test"</span>);
System.out.println(a == c); <span class="hljs-comment">// false (different objects)</span>
</code></pre>
<p>✅ You can manually add strings to the pool using <code>intern()</code>:</p>
<pre><code class="lang-java">String d = c.intern();
System.out.println(a == d); <span class="hljs-comment">// true</span>
</code></pre>
<h3 id="heading-4-why-are-strings-immutable-in-java"><strong>4. Why are Strings immutable in Java?</strong></h3>
<p><strong>Reasons:</strong></p>
<ol>
<li><p><strong>Security:</strong> Used in sensitive contexts (ClassLoader, File paths, URLs).</p>
</li>
<li><p><strong>Thread-safety:</strong> Immutable objects can be shared safely between threads.</p>
</li>
<li><p><strong>Caching:</strong> Hash code of a string is cached; immutability ensures it’s consistent.</p>
</li>
<li><p><strong>String Pool Optimization:</strong> Same string literals can be reused safely.</p>
</li>
</ol>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String s = <span class="hljs-string">"Java"</span>;
s.concat(<span class="hljs-string">" Rocks"</span>); <span class="hljs-comment">// creates a new string</span>
</code></pre>
<p>✅ Once created, the value of a String object <strong>cannot be changed</strong>.</p>
<h3 id="heading-5-how-does-equals-work-in-string"><strong>5. How does equals() work in String?</strong></h3>
<p>The <code>equals()</code> method compares <strong>the contents (values)</strong> of two strings,<br />while the <code>==</code> operator compares <strong>references</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String s1 = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Hello"</span>);
String s2 = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Hello"</span>);

System.out.println(s1 == s2);       <span class="hljs-comment">// false (different objects)</span>
System.out.println(s1.equals(s2));  <span class="hljs-comment">// true (same content)</span>
</code></pre>
<p>✅ <code>String</code> overrides <code>equals()</code> and <code>hashCode()</code> from <code>Object</code> class to compare actual text.</p>
<h3 id="heading-6-how-does-hashcode-work-in-strings"><strong>6. How does</strong> <code>hashCode()</code> work in Strings?</h3>
<ul>
<li><p>The hash code for a string is computed based on its characters:</p>
<pre><code class="lang-java">  s[<span class="hljs-number">0</span>]*<span class="hljs-number">31</span>^(n-<span class="hljs-number">1</span>) + s[<span class="hljs-number">1</span>]*<span class="hljs-number">31</span>^(n-<span class="hljs-number">2</span>) + ... + s[n-<span class="hljs-number">1</span>]
</code></pre>
</li>
<li><p>Because strings are immutable, their hash code is <strong>cached</strong> for performance.</p>
</li>
</ul>
<p>✅ Used extensively in collections like <code>HashMap</code> and <code>HashSet</code>.</p>
<h3 id="heading-7-how-do-substring-split-and-join-work"><strong>7. How do</strong> <code>substring()</code>, <code>split()</code>, and <code>join()</code> work?</h3>
<p><code>substring(begin, end)</code></p>
<ul>
<li><p>Returns part of the string.</p>
</li>
<li><p>Creates a new String (does not modify original).</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String s = <span class="hljs-string">"developer"</span>;
System.out.println(s.substring(<span class="hljs-number">0</span>, <span class="hljs-number">3</span>)); <span class="hljs-comment">// "dev"</span>
</code></pre>
<p><code>split(regex)</code></p>
<ul>
<li>Splits a string into an array based on a delimiter.</li>
</ul>
<pre><code class="lang-java">String s = <span class="hljs-string">"a,b,c"</span>;
String[] arr = s.split(<span class="hljs-string">","</span>);
</code></pre>
<p><code>String.join(delimiter, elements...)</code></p>
<pre><code class="lang-java">String result = String.join(<span class="hljs-string">"-"</span>, <span class="hljs-string">"Java"</span>, <span class="hljs-string">"Python"</span>, <span class="hljs-string">"C++"</span>);
System.out.println(result); <span class="hljs-comment">// "Java-Python-C++"</span>
</code></pre>
<h3 id="heading-8-what-is-string-interning"><strong>8. What is String interning?</strong></h3>
<p>Interning ensures that identical strings share the same reference in the <strong>String Pool</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String s1 = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Java"</span>);
String s2 = s1.intern();
String s3 = <span class="hljs-string">"Java"</span>;

System.out.println(s2 == s3); <span class="hljs-comment">// true</span>
</code></pre>
<p>✅ Improves memory efficiency, especially when there are many repeated strings.</p>
<h3 id="heading-9-what-are-common-stringbuilder-methods"><strong>9. What are common StringBuilder methods?</strong></h3>
<ul>
<li><p><code>append()</code> – concatenates data</p>
</li>
<li><p><code>insert()</code> – inserts at position</p>
</li>
<li><p><code>delete()</code> – removes substring</p>
</li>
<li><p><code>reverse()</code> – reverses content</p>
</li>
<li><p><code>capacity()</code> – returns current buffer capacity</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">StringBuilder sb = <span class="hljs-keyword">new</span> StringBuilder(<span class="hljs-string">"Hello"</span>);
sb.append(<span class="hljs-string">" World"</span>).reverse();
System.out.println(sb); <span class="hljs-comment">// "dlroW olleH"</span>
</code></pre>
<h3 id="heading-10-can-we-make-string-mutable-in-java"><strong>10. Can we make String mutable in Java?</strong></h3>
<p>Not directly.<br />However, you can <strong>simulate mutability</strong> using:</p>
<ul>
<li><p><code>StringBuilder</code> or <code>StringBuffer</code></p>
</li>
<li><p>Reflection (not recommended)</p>
</li>
<li><p>Creating a wrapper class with a mutable reference internally</p>
</li>
</ul>
<h2 id="heading-java-keywords-and-modifiers">Java Keywords and Modifiers</h2>
<h3 id="heading-1-difference-between-final-finally-and-finalize"><strong>1. Difference between final, finally, and finalize?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Keyword</strong></td><td><strong>Purpose</strong></td><td><strong>Example</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>final</strong></td><td>Restricts modification</td><td><code>final int x = 10;</code> or <code>final class MyClass</code></td></tr>
<tr>
<td><strong>finally</strong></td><td>Block to execute after try/catch</td><td><code>try {…} finally {…}</code></td></tr>
<tr>
<td><strong>finalize()</strong></td><td>Called by GC before object is destroyed</td><td><code>protected void finalize() {…}</code></td></tr>
</tbody>
</table>
</div><p><strong>Summary:</strong></p>
<ul>
<li><p><code>final</code> → compile-time constant, prevents inheritance/overriding</p>
</li>
<li><p><code>finally</code> → runtime block for cleanup</p>
</li>
<li><p><code>finalize()</code> → deprecated method, used for cleanup before garbage collection</p>
</li>
</ul>
<h3 id="heading-2-what-does-static-mean"><strong>2. What does static mean?</strong></h3>
<ul>
<li><p><strong>Static</strong> members belong to the <strong>class</strong>, not instances.</p>
</li>
<li><p><strong>Static variable:</strong> Shared across all objects</p>
</li>
<li><p><strong>Static method:</strong> Can be called without an object</p>
</li>
<li><p><strong>Static block:</strong> Executes once at class loading</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> count;
    <span class="hljs-keyword">static</span> { System.out.println(<span class="hljs-string">"Class loaded"</span>); }
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Static method"</span>); }
}
Demo.show();
System.out.println(Demo.count);
</code></pre>
<p>✅ Use static for memory efficiency and shared state.</p>
<h3 id="heading-3-what-is-transient"><strong>3. What is transient?</strong></h3>
<ul>
<li><p><strong>Transient</strong> is a keyword used in <strong>serialization</strong>.</p>
</li>
<li><p>Fields marked as transient are <strong>not serialized</strong>.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">transient</span> String password; <span class="hljs-comment">// won’t be saved</span>
}
</code></pre>
<p>✅ Useful for sensitive data like passwords or temporary fields.</p>
<h3 id="heading-4-what-is-volatile"><strong>4. What is volatile?</strong></h3>
<ul>
<li><p>Ensures <strong>visibility</strong> of changes across threads.</p>
</li>
<li><p>Guarantees that <strong>reads/writes go directly to main memory</strong>.</p>
</li>
<li><p>Does <strong>not</strong> guarantee atomicity.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">volatile</span> <span class="hljs-keyword">boolean</span> running = <span class="hljs-keyword">true</span>;

<span class="hljs-keyword">while</span> (running) { 
    <span class="hljs-comment">/* do work */</span> 
}
</code></pre>
<p>Without <code>volatile</code>, one thread may never see the updated value.</p>
<h3 id="heading-5-difference-between-this-and-super"><strong>5. Difference between this and super?</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Keyword</strong></td><td><strong>Purpose</strong></td><td><strong>Example</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>this</strong></td><td>Refers to current object</td><td><code>this.name = name;</code></td></tr>
<tr>
<td><strong>super</strong></td><td>Refers to parent class</td><td><code>super.toString();</code></td></tr>
</tbody>
</table>
</div><ul>
<li><p><code>this()</code> → calls current class constructor</p>
</li>
<li><p><code>super()</code> → calls parent class constructor</p>
</li>
<li><p>Both must be the <strong>first statement</strong> in constructor when used</p>
</li>
</ul>
<h3 id="heading-6-additional-notes-on-keywordsmodifiers"><strong>6. Additional Notes on Keywords/Modifiers</strong></h3>
<ul>
<li><p><strong>abstract:</strong> Cannot instantiate class, may contain abstract methods</p>
</li>
<li><p><strong>synchronized:</strong> Ensures mutual exclusion for threads</p>
</li>
<li><p><strong>native:</strong> Method implemented in platform-specific code (C/C++)</p>
</li>
<li><p><strong>strictfp:</strong> Ensures floating-point calculations are platform-independent</p>
</li>
<li><p><strong>default (in interfaces):</strong> Provides default method implementation</p>
</li>
<li><p><strong>var (Java 10+):</strong> Type inference for local variables</p>
</li>
</ul>
<h2 id="heading-java-inner-classes">Java Inner Classes</h2>
<h3 id="heading-1-what-are-inner-classes"><strong>1. What are inner classes?</strong></h3>
<p>An <strong>inner class</strong> is a class defined <strong>within another class</strong>.<br />They allow logical grouping of classes and access to <strong>private members</strong> of the outer class.</p>
<p><strong>Types of inner classes:</strong></p>
<ol>
<li><p><strong>Member (non-static) inner class</strong></p>
</li>
<li><p><strong>Static nested class</strong></p>
</li>
<li><p><strong>Local inner class</strong></p>
</li>
<li><p><strong>Anonymous inner class</strong></p>
</li>
</ol>
<h3 id="heading-2-what-are-static-nested-classes"><strong>2. What are static nested classes?</strong></h3>
<ul>
<li><p>A <strong>static nested class</strong> is declared with the <code>static</code> keyword.</p>
</li>
<li><p>Unlike member inner classes, it <strong>does not have access to instance variables</strong> of the outer class.</p>
</li>
<li><p>Can be instantiated without an object of the outer class.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Outer</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Nested</span> </span>{
        <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">show</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Static nested class"</span>); }
    }
}
Outer.Nested nested = <span class="hljs-keyword">new</span> Outer.Nested();
nested.show();
</code></pre>
<p>✅ Useful for <strong>grouping classes</strong> logically and reducing namespace pollution.</p>
<h3 id="heading-3-difference-between-local-anonymous-and-member-classes"><strong>3. Difference between local, anonymous, and member classes</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Type</strong></td><td><strong>Definition</strong></td><td><strong>Scope</strong></td><td><strong>Example</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Member inner class</strong></td><td>Defined at class level (non-static)</td><td>Can access outer class members</td><td><code>class Outer { class Inner {} }</code></td></tr>
<tr>
<td><strong>Static nested class</strong></td><td>Defined with <code>static</code> keyword</td><td>Only static members of outer class</td><td><code>Outer.Nested nested = new Outer.Nested();</code></td></tr>
<tr>
<td><strong>Local inner class</strong></td><td>Defined inside a method</td><td>Only visible within method</td><td><code>void method() { class Local {} }</code></td></tr>
<tr>
<td><strong>Anonymous inner class</strong></td><td>No class name, used for instant implementation</td><td>Usually for implementing interfaces or extending classes</td><td><code>Runnable r = new Runnable() { public void run() {} };</code></td></tr>
</tbody>
</table>
</div><p><strong>Key points:</strong></p>
<ul>
<li><p>Member inner classes hold a <strong>reference to outer class</strong>.</p>
</li>
<li><p>Static nested classes <strong>don’t hold outer class reference</strong>, so memory footprint is smaller.</p>
</li>
<li><p>Anonymous classes are great for <strong>event handlers and callbacks</strong>.</p>
</li>
</ul>
<p><strong>Example of anonymous inner class:</strong></p>
<pre><code class="lang-java">Runnable r = <span class="hljs-keyword">new</span> Runnable() {
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Anonymous Runnable"</span>);
    }
};
<span class="hljs-keyword">new</span> Thread(r).start();
</code></pre>
<h3 id="heading-4-when-to-use-inner-classes"><strong>4. When to use inner classes?</strong></h3>
<ul>
<li><p>When a class is <strong>only relevant to its outer class</strong>.</p>
</li>
<li><p>For <strong>callbacks, listeners, or adapters</strong>.</p>
</li>
<li><p>To <strong>encapsulate helper classes</strong> without exposing them publicly.</p>
</li>
<li><p>To <strong>access outer class private members</strong> without getters/setters.</p>
</li>
</ul>
<p>✅ Correct use of inner classes improves <strong>code readability, encapsulation, and design</strong>.</p>
<h2 id="heading-design-principles-patterns">Design Principles / Patterns</h2>
<h3 id="heading-1-what-is-solid"><strong>1. What is SOLID?</strong></h3>
<p><a target="_blank" href="https://blog.ashutoshkrris.in/solid-principles-for-better-software-design"><strong>SOLID</strong></a> is an acronym for five design principles that make code <strong>more maintainable, scalable, and testable</strong>:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Principle</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>S – Single Responsibility Principle (SRP)</strong></td><td>A class should have <strong>only one reason to change</strong>. Each class should focus on a single functionality.</td></tr>
<tr>
<td><strong>O – Open/Closed Principle (OCP)</strong></td><td>Classes should be <strong>open for extension, closed for modification</strong>.</td></tr>
<tr>
<td><strong>L – Liskov Substitution Principle (LSP)</strong></td><td>Subclasses should be <strong>substitutable</strong> for their parent classes without affecting program correctness.</td></tr>
<tr>
<td><strong>I – Interface Segregation Principle (ISP)</strong></td><td>Clients should <strong>not be forced to depend on methods they don’t use</strong>. Prefer multiple small interfaces over one large interface.</td></tr>
<tr>
<td><strong>D – Dependency Inversion Principle (DIP)</strong></td><td>High-level modules should <strong>not depend on low-level modules</strong>. Both should depend on <strong>abstractions</strong>.</td></tr>
</tbody>
</table>
</div><p>✅ These principles are key to <strong>writing clean and scalable Java applications</strong>.</p>
<h3 id="heading-2-what-is-the-singleton-pattern"><strong>2. What is the Singleton pattern?</strong></h3>
<p>The <strong>Singleton pattern</strong> ensures a class has <strong>only one instance</strong> and provides a global access point.</p>
<p><strong>Implementation (Thread-safe, lazy initialization):</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">volatile</span> Singleton instance;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>{} <span class="hljs-comment">// private constructor</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">synchronized</span>(Singleton.class) {
                <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
                    instance = <span class="hljs-keyword">new</span> Singleton();
                }
            }
        }
        <span class="hljs-keyword">return</span> instance;
    }
}
</code></pre>
<p>✅ Use cases:</p>
<ul>
<li><p>Logger</p>
</li>
<li><p>Configuration manager</p>
</li>
<li><p>Thread pool manager</p>
</li>
</ul>
<h3 id="heading-3-how-to-implement-an-immutable-class"><strong>3. How to implement an immutable class?</strong></h3>
<p><strong>Steps to make a class immutable:</strong></p>
<ol>
<li><p>Declare class as <code>final</code>.</p>
</li>
<li><p>Make all fields <code>private</code> and <code>final</code>.</p>
</li>
<li><p>No setters.</p>
</li>
<li><p>Return <strong>deep copies</strong> of mutable objects.</p>
</li>
</ol>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Employee</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> name; }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> age; }
}
</code></pre>
<p>✅ Immutable objects are <strong>thread-safe</strong> and prevent unintended state changes.</p>
<h3 id="heading-4-what-is-the-factory-pattern"><strong>4. What is the Factory pattern?</strong></h3>
<p>The <strong>Factory pattern</strong> provides a <strong>way to create objects without exposing instantiation logic</strong>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> </span>{ <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>; }

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Circle"</span>); }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Square</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{ System.out.println(<span class="hljs-string">"Square"</span>); }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ShapeFactory</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Shape <span class="hljs-title">getShape</span><span class="hljs-params">(String type)</span> </span>{
        <span class="hljs-keyword">if</span> (type.equalsIgnoreCase(<span class="hljs-string">"circle"</span>)) <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Circle();
        <span class="hljs-keyword">if</span> (type.equalsIgnoreCase(<span class="hljs-string">"square"</span>)) <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Square();
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Unknown shape"</span>);
    }
}

<span class="hljs-comment">// Usage</span>
Shape s = ShapeFactory.getShape(<span class="hljs-string">"circle"</span>);
s.draw();
</code></pre>
<p>✅ Use when object creation <strong>logic is complex</strong> or depends on conditions.</p>
<h3 id="heading-5-what-is-dependency-injection-di"><strong>5. What is Dependency Injection (DI)?</strong></h3>
<p><strong>Dependency Injection</strong> is a <strong>design pattern</strong> where an object receives its dependencies from <strong>external sources</strong> rather than creating them internally.</p>
<p><strong>Types of DI:</strong></p>
<ul>
<li><p><strong>Constructor injection</strong> – dependencies passed via constructor</p>
</li>
<li><p><strong>Setter injection</strong> – dependencies set via setters</p>
</li>
<li><p><strong>Interface injection</strong> – using an interface to inject dependencies (less common)</p>
</li>
</ul>
<p><strong>Example (Constructor DI):</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Service</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Repository repo;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Service</span><span class="hljs-params">(Repository repo)</span> </span>{ <span class="hljs-keyword">this</span>.repo = repo; }
}
Repository repo = <span class="hljs-keyword">new</span> Repository();
Service service = <span class="hljs-keyword">new</span> Service(repo);
</code></pre>
<p>✅ Benefits:</p>
<ul>
<li><p>Promotes <strong>loose coupling</strong></p>
</li>
<li><p>Easier <strong>unit testing</strong></p>
</li>
<li><p>Improves <strong>maintainability</strong></p>
</li>
</ul>
<h2 id="heading-jvm-internals-and-performance">JVM Internals and Performance</h2>
<h3 id="heading-1-what-happens-when-you-run-a-java-program"><strong>1. What happens when you run a Java program?</strong></h3>
<p><strong>Steps in Java program execution:</strong></p>
<ol>
<li><p><strong>Compilation:</strong> <code>.java</code> source code is compiled into <code>.class</code> bytecode using <code>javac</code>.</p>
</li>
<li><p><strong>Class loading:</strong> JVM loads the <code>.class</code> files into memory using ClassLoaders.</p>
</li>
<li><p><strong>Bytecode verification:</strong> Ensures code is valid and doesn’t violate JVM constraints.</p>
</li>
<li><p><strong>Execution:</strong> Just-In-Time (JIT) compiler converts bytecode into native machine code for performance.</p>
</li>
<li><p><strong>Memory allocation:</strong> Objects are created in the heap; references stored in stack.</p>
</li>
<li><p><strong>Garbage Collection:</strong> Unreferenced objects are cleaned automatically.</p>
</li>
</ol>
<p>✅ Key point: JVM allows <strong>platform independence</strong> by abstracting underlying OS and hardware.</p>
<h3 id="heading-2-explain-class-loading-process"><strong>2. Explain class loading process</strong></h3>
<p>Class loading is handled by the JVM in <strong>three phases</strong>:</p>
<ol>
<li><p><strong>Loading:</strong> Loads <code>.class</code> file into memory using ClassLoader.</p>
</li>
<li><p><strong>Linking:</strong></p>
<ul>
<li><p><strong>Verification:</strong> Ensures bytecode integrity</p>
</li>
<li><p><strong>Preparation:</strong> Allocates memory for static variables</p>
</li>
<li><p><strong>Resolution:</strong> Resolves symbolic references</p>
</li>
</ul>
</li>
<li><p><strong>Initialization:</strong> Executes static blocks and initializes static fields.</p>
</li>
</ol>
<h3 id="heading-3-what-is-the-role-of-classloader"><strong>3. What is the role of ClassLoader?</strong></h3>
<p><strong>ClassLoader</strong> loads Java classes into JVM <strong>at runtime</strong>.</p>
<p><strong>Types of ClassLoaders:</strong></p>
<ol>
<li><p><strong>Bootstrap ClassLoader:</strong> Loads core Java classes (rt.jar)</p>
</li>
<li><p><strong>Extension ClassLoader:</strong> Loads JDK extension libraries (<code>lib/ext</code>)</p>
</li>
<li><p><strong>Application ClassLoader:</strong> Loads classes from classpath (your code)</p>
</li>
<li><p><strong>Custom ClassLoader:</strong> Can be created for dynamic class loading</p>
</li>
</ol>
<p>✅ ClassLoader ensures <strong>lazy loading</strong> — classes are loaded only when needed.</p>
<h3 id="heading-4-how-does-java-achieve-platform-independence"><strong>4. How does Java achieve platform independence?</strong></h3>
<ul>
<li><p>Java code is compiled into <strong>bytecode</strong> (<code>.class</code> file), not native machine code.</p>
</li>
<li><p>JVM <strong>interprets bytecode</strong> or uses JIT to convert to <strong>native code</strong>.</p>
</li>
<li><p>Same bytecode can run on any platform with a compatible JVM.</p>
</li>
</ul>
<p><strong>Key principle:</strong> Write Once, Run Anywhere (WORA).</p>
<h3 id="heading-5-how-to-improve-java-performance"><strong>5. How to improve Java performance?</strong></h3>
<ul>
<li><p><strong>Memory management:</strong></p>
<ul>
<li><p>Use proper <strong>data structures</strong> (ArrayList vs LinkedList)</p>
</li>
<li><p>Minimize object creation, reuse objects</p>
</li>
</ul>
</li>
<li><p><strong>Multithreading:</strong> Use <strong>ExecutorService</strong>, parallel streams wisely</p>
</li>
<li><p><strong>Collections:</strong> Use <strong>Concurrent collections</strong> for thread safety</p>
</li>
<li><p><strong>Garbage Collection tuning:</strong> Adjust <strong>heap size</strong> and <strong>GC algorithm</strong></p>
</li>
<li><p><strong>String handling:</strong> Use <strong>StringBuilder</strong> instead of String concatenation in loops</p>
</li>
<li><p><strong>Profiling:</strong> Use tools like <strong>VisualVM, JConsole</strong> to detect bottlenecks</p>
</li>
</ul>
<h3 id="heading-6-garbage-collection-overview"><strong>6. Garbage Collection overview</strong></h3>
<ul>
<li><p><strong>Automatic memory management</strong> by JVM</p>
</li>
<li><p>Removes <strong>unreachable objects</strong> from heap</p>
</li>
<li><p>Common collectors: Serial, Parallel, CMS, G1</p>
</li>
<li><p>GC events: Minor GC (young generation), Major GC (old generation)</p>
</li>
<li><p><strong>Finalize()</strong> is called before GC (deprecated in Java 9+)</p>
</li>
</ul>
<p>✅ Modern JVM uses <strong>generational GC</strong> for efficiency.</p>
<h3 id="heading-7-heap-vs-stack"><strong>7. Heap vs Stack</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Memory Area</strong></td><td><strong>Purpose</strong></td><td><strong>Example</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Heap</strong></td><td>Stores objects and arrays</td><td><code>new Employee()</code></td></tr>
<tr>
<td><strong>Stack</strong></td><td>Stores method call frames, local variables</td><td><code>int x = 10;</code></td></tr>
</tbody>
</table>
</div><ul>
<li><p>Stack memory is <strong>LIFO</strong>, automatically cleaned.</p>
</li>
<li><p>Heap memory is <strong>shared</strong>, cleaned by GC.</p>
</li>
</ul>
<h3 id="heading-8-permgen-vs-metaspace"><strong>8. PermGen vs Metaspace</strong></h3>
<ul>
<li><p><strong>PermGen (Java 7 and below):</strong> Stores class metadata; fixed size → risk of <code>OutOfMemoryError</code>.</p>
</li>
<li><p><strong>Metaspace (Java 8+):</strong> Dynamically resizable; stored in native memory → reduces class loading errors.</p>
</li>
</ul>
<h2 id="heading-miscellaneous-java-concepts">Miscellaneous Java Concepts</h2>
<h3 id="heading-1-serialization-vs-deserialization"><strong>1. Serialization vs Deserialization</strong></h3>
<ul>
<li><p><strong>Serialization:</strong> Converts a Java object into a byte stream to save to disk or send over a network.</p>
</li>
<li><p><strong>Deserialization:</strong> Converts the byte stream back into a Java object.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Serialization</span>
ObjectOutputStream oos = <span class="hljs-keyword">new</span> ObjectOutputStream(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">"data.obj"</span>));
oos.writeObject(employee);

<span class="hljs-comment">// Deserialization</span>
ObjectInputStream ois = <span class="hljs-keyword">new</span> ObjectInputStream(<span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">"data.obj"</span>));
Employee e = (Employee) ois.readObject();
</code></pre>
<p><strong>Notes:</strong></p>
<ul>
<li><p>Use <code>transient</code> keyword for fields that shouldn’t be serialized.</p>
</li>
<li><p>Serializable classes must implement <code>Serializable</code>.</p>
</li>
</ul>
<h3 id="heading-2-what-is-a-marker-interface"><strong>2. What is a marker interface?</strong></h3>
<ul>
<li><p>An interface <strong>without methods</strong> used to mark a class with special behavior.</p>
</li>
<li><p>Examples: <code>Serializable</code>, <code>Cloneable</code>, <code>Remote</code>.</p>
</li>
</ul>
<p><strong>Purpose:</strong> Provides <strong>metadata</strong> to JVM or frameworks.</p>
<h3 id="heading-3-what-is-instanceof-keyword"><strong>3. What is instanceof keyword?</strong></h3>
<ul>
<li>Checks if an object is an instance of a specific class or implements an interface.</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">String s = <span class="hljs-string">"Java"</span>;
<span class="hljs-keyword">if</span> (s <span class="hljs-keyword">instanceof</span> String) {
    System.out.println(<span class="hljs-string">"s is a String"</span>);
}
</code></pre>
<p>✅ Always returns <code>true</code> for null checks: <code>null instanceof String</code> → <code>false</code>.</p>
<h3 id="heading-4-what-is-reflection-api"><strong>4. What is reflection API?</strong></h3>
<ul>
<li><p><strong>Reflection</strong> allows inspecting and manipulating classes, methods, and fields <strong>at runtime</strong>.</p>
</li>
<li><p>Can be used to:</p>
<ul>
<li><p>Get class info (<code>Class&lt;?&gt; clazz = obj.getClass();</code>)</p>
</li>
<li><p>Access private fields/methods</p>
</li>
<li><p>Dynamically create instances</p>
</li>
</ul>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Class&lt;?&gt; clazz = Class.forName(<span class="hljs-string">"java.util.ArrayList"</span>);
Object obj = clazz.getDeclaredConstructor().newInstance();
</code></pre>
<p>✅ Useful for frameworks like Spring, Hibernate, and testing tools.</p>
<h3 id="heading-5-what-is-autoboxing-and-unboxing"><strong>5. What is autoboxing and unboxing?</strong></h3>
<ul>
<li><p><strong>Autoboxing:</strong> Automatic conversion from primitive to wrapper class</p>
<pre><code class="lang-java">  <span class="hljs-keyword">int</span> x = <span class="hljs-number">10</span>;
  Integer y = x; <span class="hljs-comment">// autoboxing</span>
</code></pre>
</li>
<li><p><strong>Unboxing:</strong> Wrapper class → primitive</p>
<pre><code class="lang-java">  Integer a = <span class="hljs-number">20</span>;
  <span class="hljs-keyword">int</span> b = a; <span class="hljs-comment">// unboxing</span>
</code></pre>
</li>
</ul>
<h3 id="heading-6-what-is-enum-in-java"><strong>6. What is enum in Java?</strong></h3>
<ul>
<li><p><code>enum</code> is a <strong>special class representing a fixed set of constants</strong>.</p>
</li>
<li><p>Can have <strong>fields, methods, and constructors</strong>.</p>
</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">Day</span> </span>{ MONDAY, TUESDAY, WEDNESDAY }
Day today = Day.MONDAY;
</code></pre>
<p>✅ Useful for <strong>type safety</strong> instead of string constants.</p>
<h3 id="heading-7-can-we-override-private-methods"><strong>7. Can we override private methods?</strong></h3>
<ul>
<li><p><strong>No</strong>, private methods are not visible to subclasses.</p>
</li>
<li><p>They are <strong>class-specific</strong> and <strong>cannot be overridden</strong>, but they can be <strong>redeclared</strong> in a subclass.</p>
</li>
</ul>
<h3 id="heading-8-can-we-overload-main-method"><strong>8. Can we overload main method?</strong></h3>
<ul>
<li><strong>Yes</strong>, you can overload <code>main</code>:</li>
</ul>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{ }
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] args)</span> </span>{ }
</code></pre>
<ul>
<li>JVM always calls the <strong>String[] main method</strong>.</li>
</ul>
<h3 id="heading-9-can-constructor-be-private"><strong>9. Can constructor be private?</strong></h3>
<ul>
<li><p><strong>Yes</strong>, used in <strong>Singleton pattern</strong> or factory methods.</p>
</li>
<li><p>Prevents direct instantiation from outside the class.</p>
</li>
</ul>
<h3 id="heading-10-what-are-annotations-in-java"><strong>10. What are annotations in Java?</strong></h3>
<ul>
<li><p>Metadata for <strong>classes, methods, fields</strong>.</p>
</li>
<li><p>Examples: <code>@Override</code>, <code>@Deprecated</code>, <code>@FunctionalInterface</code></p>
</li>
<li><p>Custom annotation example:</p>
</li>
</ul>
<pre><code class="lang-java"><span class="hljs-meta">@Retention(RetentionPolicy.RUNTIME)</span>
<span class="hljs-meta">@Target(ElementType.METHOD)</span>
<span class="hljs-meta">@interface</span> Test { 
}
</code></pre>
<h3 id="heading-11-what-is-javabeans"><strong>11. What is JavaBeans?</strong></h3>
<ul>
<li><p><strong>JavaBean:</strong> A reusable class following:</p>
<ul>
<li><p>Private fields</p>
</li>
<li><p>Public getters and setters</p>
</li>
<li><p>No-arg constructor</p>
</li>
<li><p>Serializable</p>
</li>
</ul>
</li>
</ul>
<p>✅ Used for <strong>encapsulation</strong> and frameworks like JSP, JSF, and Spring.</p>
<h3 id="heading-12-what-is-var-keyword-in-java"><strong>12. What is var keyword in Java?</strong></h3>
<ul>
<li>Introduced in <strong>Java 10</strong> for <strong>local variable type inference</strong>.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">var</span> name = <span class="hljs-string">"Ashutosh"</span>; <span class="hljs-comment">// inferred as String</span>
</code></pre>
<ul>
<li>Cannot be used for method parameters, fields, or return type.</li>
</ul>
<h3 id="heading-13-what-are-records-in-java"><strong>13. What are records in Java?</strong></h3>
<ul>
<li><p>Introduced in <strong>Java 14</strong> as <strong>immutable data carriers</strong>.</p>
</li>
<li><p>Automatically generate <strong>constructor, getters, equals, hashCode, toString</strong>.</p>
</li>
</ul>
<pre><code class="lang-java"><span class="hljs-function">record <span class="hljs-title">Employee</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{ }
Employee e = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"John"</span>, <span class="hljs-number">25</span>);
</code></pre>
<p>✅ Great for <strong>DTOs and value objects</strong>.</p>
<blockquote>
<p>Learn more about records <a target="_blank" href="https://blog.ashutoshkrris.in/dto-vs-record-in-java-which-should-you-use">here</a>.</p>
</blockquote>
<h3 id="heading-14-difference-between-compile-time-and-runtime-errors"><strong>14. Difference between compile-time and runtime errors</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Type</td><td>When occurs</td><td>Example</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Compile-time error</strong></td><td>During compilation</td><td>Syntax error, missing semicolon</td></tr>
<tr>
<td><strong>Runtime error</strong></td><td>During program execution</td><td>NullPointerException, ArrayIndexOutOfBounds</td></tr>
</tbody>
</table>
</div><h2 id="heading-real-world-scenario-based-questions">Real-World Scenario-Based Questions</h2>
<h3 id="heading-1-how-would-you-optimize-a-large-collection-for-search"><strong>1. How would you optimize a large collection for search?</strong></h3>
<p><strong>Scenario:</strong> You have a large dataset and need frequent lookups.</p>
<p><strong>Approach:</strong></p>
<ol>
<li><p><strong>Choose the right data structure:</strong></p>
<ul>
<li><p><code>HashMap</code> for O(1) key-value lookup.</p>
</li>
<li><p><code>TreeMap</code> if sorted order is required (O(log n) lookup).</p>
</li>
<li><p><code>HashSet</code> for unique element search.</p>
</li>
</ul>
</li>
<li><p><strong>Indexing:</strong> Precompute indices for frequent queries.</p>
</li>
<li><p><strong>Use streams with parallel processing</strong> if data is very large.</p>
</li>
<li><p><strong>Avoid unnecessary object creation:</strong> Use primitives or immutable objects.</p>
</li>
<li><p><strong>Memory considerations:</strong> If memory is tight, consider using compressed data structures or disk-based solutions.</p>
</li>
</ol>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">Map&lt;String, Employee&gt; employeeMap = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
<span class="hljs-keyword">for</span>(Employee e: employees) {
    employeeMap.put(e.getId(), e);
}
<span class="hljs-comment">// Lookup by ID is now O(1)</span>
</code></pre>
<h3 id="heading-2-how-to-handle-concurrency-in-a-shared-resource"><strong>2. How to handle concurrency in a shared resource?</strong></h3>
<p><strong>Scenario:</strong> Multiple threads need to access/update shared data.</p>
<p><strong>Approach:</strong></p>
<ol>
<li><p><strong>Synchronized blocks/methods:</strong></p>
<pre><code class="lang-java"> <span class="hljs-keyword">synchronized</span>(<span class="hljs-keyword">this</span>) {
     <span class="hljs-comment">// critical section</span>
 }
</code></pre>
</li>
<li><p><strong>Concurrent Collections:</strong> Use <code>ConcurrentHashMap</code>, <code>CopyOnWriteArrayList</code>.</p>
</li>
<li><p><strong>Locks:</strong> Use <code>ReentrantLock</code> for fine-grained control.</p>
</li>
<li><p><strong>Atomic Variables:</strong> Use <code>AtomicInteger</code>, <code>AtomicReference</code> for atomic operations.</p>
</li>
<li><p><strong>Avoid deadlocks:</strong> Always acquire locks in consistent order.</p>
</li>
</ol>
<p>✅ Modern Java encourages <strong>lock-free structures</strong> and <strong>immutability</strong> where possible.</p>
<h3 id="heading-3-whats-your-approach-for-debugging-memory-leaks"><strong>3. What’s your approach for debugging memory leaks?</strong></h3>
<p><strong>Steps:</strong></p>
<ol>
<li><p><strong>Identify symptoms:</strong> High heap usage, <code>OutOfMemoryError</code>, slow performance.</p>
</li>
<li><p><strong>Analyze heap dumps:</strong> Use tools like <strong>VisualVM, Eclipse MAT, JProfiler</strong>.</p>
</li>
<li><p><strong>Check references:</strong> Look for <strong>unreleased objects</strong>, static collections, caches.</p>
</li>
<li><p><strong>Fix common causes:</strong></p>
<ul>
<li><p>Remove unused listeners or callbacks</p>
</li>
<li><p>Use <code>WeakReference</code> where needed</p>
</li>
<li><p>Clear collections properly</p>
</li>
</ul>
</li>
<li><p><strong>Test thoroughly:</strong> Run under load to confirm memory usage stabilizes.</p>
</li>
</ol>
<h3 id="heading-4-how-to-ensure-thread-safety-without-performance-issues"><strong>4. How to ensure thread safety without performance issues?</strong></h3>
<p><strong>Scenario:</strong> High-concurrency application.</p>
<p><strong>Approach:</strong></p>
<ol>
<li><p>Prefer <strong>immutable objects</strong> to avoid synchronization overhead.</p>
</li>
<li><p>Use <strong>concurrent collections</strong> (<code>ConcurrentHashMap</code>, <code>ConcurrentLinkedQueue</code>) instead of synchronized versions.</p>
</li>
<li><p>Minimize <strong>synchronized blocks</strong> to only critical sections.</p>
</li>
<li><p>Use <strong>atomic variables</strong> for counters or flags.</p>
</li>
<li><p>Consider <strong>ReadWriteLock</strong> if reads dominate writes.</p>
</li>
</ol>
<p>✅ Key: Balance <strong>thread safety vs performance</strong>.</p>
<h3 id="heading-5-explain-a-situation-where-you-used-java-8-features-to-simplify-code"><strong>5. Explain a situation where you used Java 8 features to simplify code</strong></h3>
<p><strong>Example Answer:</strong></p>
<blockquote>
<p>“In a recent project, we had a list of employees and needed to filter those in a specific department, sort by salary, and collect names. Using Java 8 Streams and lambdas, I could do it in one readable statement instead of nested loops:</p>
<pre><code class="lang-java">List&lt;String&gt; names = employees.stream()
    .filter(e -&gt; e.getDepartment().equals(<span class="hljs-string">"Engineering"</span>))
    .sorted(Comparator.comparing(Employee::getSalary).reversed())
    .map(Employee::getName)
    .collect(Collectors.toList());
</code></pre>
<p>This approach reduced boilerplate code, improved readability, and was easy to maintain.”</p>
</blockquote>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>This guide covers <strong>all essential Core Java concepts, coding patterns, and real-world scenarios</strong> needed to excel in Java interviews in 2025. Use it to <strong>strengthen fundamentals, improve problem-solving, and confidently tackle interviews</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[DTO vs Record in Java: Which Should You Use?]]></title><description><![CDATA[In Java applications, we often need to transfer data between different layers of the application, or between services. For this purpose, we use Data Transfer Objects (DTOs). A DTO is a simple object designed to hold data, without any complex behavior...]]></description><link>https://blog.ashutoshkrris.in/dto-vs-record-in-java-which-should-you-use</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/dto-vs-record-in-java-which-should-you-use</guid><category><![CDATA[Java]]></category><category><![CDATA[Records]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sun, 29 Sep 2024 19:13:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727637193632/82341f89-6db7-4b75-9f37-dcf56814cdce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In Java applications, we often need to transfer data between different layers of the application, or between services. For this purpose, we use <strong>Data Transfer Objects (DTOs)</strong>. A DTO is a simple object designed to hold data, without any complex behavior or logic. Its job is to bundle data and pass it along where needed.</p>
<p>Now, Java introduced a new feature in <strong>Java 14</strong>, called <strong>Records</strong>. These are special types of classes that focus on holding data, just like DTOs. The big difference is that Records do a lot of the repetitive work for us. For example, they automatically create methods to get the data (like getters), and they handle equality checks, <code>toString()</code>, and more. This feature became fully available in <strong>Java 16</strong>, making Records a modern, clean way to work with data in Java.</p>
<p>So, why are we comparing DTOs and Records? Because they both serve a similar purpose — carrying data. However, understanding when to use one over the other is important as Java continues to evolve. In this article, we’ll explore the differences and help you decide which one fits your needs better, especially if you’re working on modern Java applications.</p>
<h2 id="heading-what-is-a-dto">What is a DTO?</h2>
<p>A <strong>Data Transfer Object (DTO)</strong> is a simple Java object that is used to move data between different parts of an application. Think of it as a container for carrying data between layers of your application. For example, in a web application, a DTO might be used to transfer data from the service layer to the controller, or from the controller to the view layer.</p>
<p>DTOs help keep the different parts of an application separated, making the code more organized and easier to maintain. They typically don’t have any business logic or complex behavior. Instead, they just hold data.</p>
<h3 id="heading-how-are-dtos-implemented">How are DTOs implemented?</h3>
<p>DTOs are usually implemented as regular Java classes. A typical DTO includes:</p>
<ul>
<li><p><strong>Private fields</strong> for the data it holds.</p>
</li>
<li><p><strong>Getters and Setters</strong> to access and modify the data.</p>
</li>
<li><p>A <strong>Constructor</strong> to create the object.</p>
</li>
<li><p><strong>Override methods</strong> like <code>toString()</code>, <code>hashCode()</code>, and <code>equals()</code> for comparing and printing the object in a meaningful way.</p>
</li>
</ul>
<p>Here’s an example of a <strong>UserDTO</strong> class :</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Objects;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">private</span> String email;

    <span class="hljs-comment">// Constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserDTO</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, String email)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.email = email;
    }

    <span class="hljs-comment">// Getters and Setters</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> email;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setEmail</span><span class="hljs-params">(String email)</span> </span>{
        <span class="hljs-keyword">this</span>.email = email;
    }

    <span class="hljs-comment">// Overriding toString method for meaningful output</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"UserDTO{"</span> +
                <span class="hljs-string">"name='"</span> + name + <span class="hljs-string">'\''</span> +
                <span class="hljs-string">", age="</span> + age +
                <span class="hljs-string">", email='"</span> + email + <span class="hljs-string">'\''</span> +
                <span class="hljs-string">'}'</span>;
    }

    <span class="hljs-comment">// Overriding equals method for object comparison</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">equals</span><span class="hljs-params">(Object o)</span> </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span> == o) <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">if</span> (o == <span class="hljs-keyword">null</span> || getClass() != o.getClass()) <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
        UserDTO userDTO = (UserDTO) o;
        <span class="hljs-keyword">return</span> age == userDTO.age &amp;&amp; Objects.equals(name, userDTO.name) &amp;&amp; Objects.equals(email, userDTO.email);
    }

    <span class="hljs-comment">// Overriding hashCode method</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hashCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Objects.hash(name, age, email);
    }
}
</code></pre>
<p>This <strong>UserDTO</strong> class holds information about a user: their name, age, and email. It also provides basic functionality like comparing two <code>UserDTO</code> objects (using <code>equals()</code>), generating a unique hash code (using <code>hashCode()</code>), and a <code>toString()</code> method for readable output.</p>
<blockquote>
<p>With tools like Lombok, you can avoid manually writing boilerplate code while still having a fully functional DTO. However, with <strong>Records</strong>, as we’ll explore later, Java offers an alternative that also eliminates much of the boilerplate but with a different design philosophy (immutability by default).</p>
</blockquote>
<p>Here’s how you can use the <code>UserDTO</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTOUsageExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        UserDTO user = <span class="hljs-keyword">new</span> UserDTO(<span class="hljs-string">"Ashutosh"</span>, <span class="hljs-number">25</span>, <span class="hljs-string">"ashutosh@example.com"</span>);

        <span class="hljs-comment">// Access data</span>
        System.out.println(user.getName());
        System.out.println(user.getAge());
        System.out.println(user.getEmail());

        <span class="hljs-comment">// Using the toString() method</span>
        System.out.println(user);

        <span class="hljs-comment">// Comparing records</span>
        UserDTO anotherUser = <span class="hljs-keyword">new</span> UserDTO(<span class="hljs-string">"Vishakha"</span>, <span class="hljs-number">22</span>, <span class="hljs-string">"vishakha@example.com"</span>);
        System.out.println(user.equals(anotherUser));
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Ashutosh
25
ashutosh@example.com
UserDTO{name=<span class="hljs-string">'Ashutosh'</span>, age=25, email=<span class="hljs-string">'ashutosh@example.com'</span>}
<span class="hljs-literal">false</span>
</code></pre>
<h2 id="heading-what-is-a-java-record">What is a Java Record?</h2>
<p><strong>Java Records</strong> are a special type of class introduced in <strong>Java 14</strong> (as a preview feature) and fully released in <strong>Java 16</strong>. They simplify the creation of immutable data carriers. Records are designed to hold data in a concise and readable way, and they eliminate much of the boilerplate code that traditional classes, like DTOs, require.</p>
<p>In a traditional DTO, you manually write constructors, getters, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> methods (as we did earlier). With Records, Java generates all of these for you automatically. This makes them ideal for simple, immutable objects whose main job is to carry data.</p>
<h3 id="heading-key-features-of-java-records">Key Features of Java Records</h3>
<ul>
<li><p><strong>Immutable by default</strong>: Once you create a record, you can't change its data (unlike DTOs, which are typically mutable).</p>
</li>
<li><p><strong>Compact syntax</strong>: You declare the fields and Java generates the constructor, getters, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> automatically.</p>
</li>
<li><p><strong>No setters</strong>: Since records are immutable, they don’t provide setters.</p>
</li>
</ul>
<p>Let’s create a <strong>UserRecord</strong> that represents the same user data as our earlier <strong>UserDTO</strong>, but using a record:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">UserRecord</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, String email)</span> </span>{
}
</code></pre>
<p>That's it! With just one line, Java generates:</p>
<ul>
<li><p>A <strong>constructor</strong>: <code>new UserRecord(String name, int age, String email)</code></p>
</li>
<li><p><strong>Getters</strong> for each field: <code>name()</code>, <code>age()</code>, and <code>email()</code></p>
</li>
<li><p>An <code>equals()</code> method for comparing two <code>UserRecord</code> objects.</p>
</li>
<li><p>A <code>hashCode()</code> method to generate a unique hash code.</p>
</li>
<li><p>A <code>toString()</code> method that returns a string representation like this: <code>UserRecord[name=Ashutosh, age=25, email=ashutosh@example.com]</code>.</p>
</li>
</ul>
<p>Here’s how you can use the <code>UserRecord</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserRecordUsageExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        UserRecord user = <span class="hljs-keyword">new</span> UserRecord(<span class="hljs-string">"Ashutosh"</span>, <span class="hljs-number">25</span>, <span class="hljs-string">"ashutosh@example.com"</span>);

        <span class="hljs-comment">// Access data</span>
        System.out.println(user.name());
        System.out.println(user.age());
        System.out.println(user.email());

        <span class="hljs-comment">// Using the toString() method</span>
        System.out.println(user);

        <span class="hljs-comment">// Comparing records</span>
        UserRecord anotherUser = <span class="hljs-keyword">new</span> UserRecord(<span class="hljs-string">"Vishakha"</span>, <span class="hljs-number">22</span>, <span class="hljs-string">"vishakha@example.com"</span>);
        System.out.println(user.equals(anotherUser));
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Ashutosh
25
ashutosh@example.com
UserRecord[name=Ashutosh, age=25, email=ashutosh@example.com]
<span class="hljs-literal">false</span>
</code></pre>
<p>With <strong>UserRecord</strong>, we avoided writing getters, constructors, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> manually. Java Records offer a clean, concise way to create immutable objects that only carry data.</p>
<h3 id="heading-why-use-records">Why Use Records?</h3>
<ul>
<li><p><strong>Less Boilerplate</strong>: You don’t have to write repetitive code like getters or <code>equals()</code> methods.</p>
</li>
<li><p><strong>Immutable by Design</strong>: Ensures the data can't be changed after the object is created, making it <strong>safer to use in multi-threaded environments</strong>.</p>
</li>
<li><p><strong>Clear Intent</strong>: Using a Record clearly communicates that the object is just for carrying data, without additional behavior or logic.</p>
</li>
</ul>
<h2 id="heading-comparing-dto-and-record">Comparing DTO and Record</h2>
<p>Now that we know about DTO and Records, let’s compare them in this section.</p>
<h3 id="heading-immutability">Immutability</h3>
<p><strong>Records</strong> are <strong>immutable by design</strong>, meaning once you create a record instance, you can’t change its data. This immutability ensures that the data remains <strong>consistent and thread-safe</strong> without needing any extra code. For example, in a <code>UserRecord</code>, the fields <code>name</code>, <code>age</code>, and <code>email</code> can be set only when the record is created, and they can't be modified afterward.</p>
<p>On the other hand, <strong>DTOs</strong> are typically <strong>mutable</strong>, meaning their fields can be changed after the object is created. To make DTOs immutable, you would have to explicitly avoid setters or design them carefully (e.g., using final fields). Here’s how immutability looks with a record versus a traditional DTO:</p>
<ul>
<li><p><strong>Record</strong>: Immutable by default.</p>
</li>
<li><p><strong>DTO</strong>: Requires manual enforcement for immutability, which can lead to more complex code and potential bugs.</p>
</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImmutabilityExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        UserDTO userDTO = <span class="hljs-keyword">new</span> UserDTO(<span class="hljs-string">"Ashutosh"</span>, <span class="hljs-number">25</span>, <span class="hljs-string">"ashutosh@example.com"</span>);
        userDTO.setAge(<span class="hljs-number">26</span>);  <span class="hljs-comment">// DTO allows this by default.</span>

        UserRecord userRecord = <span class="hljs-keyword">new</span> UserRecord(<span class="hljs-string">"Ashutosh"</span>, <span class="hljs-number">25</span>, <span class="hljs-string">"ashutosh@example.com"</span>);
        userRecord.name = <span class="hljs-string">"Jane"</span>; <span class="hljs-comment">// This would result in a compile-time error.</span>
    }
}
</code></pre>
<h3 id="heading-boilerplate-code">Boilerplate Code</h3>
<p>One of the biggest advantages of <strong>Records</strong> is that they significantly <strong>reduce boilerplate code</strong>. When using a DTO, you often have to manually write getters, setters, constructors, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> methods. With Records, all of this is generated for you automatically.</p>
<p>In contrast, traditional <strong>DTOs</strong> require more manual coding. Although tools like <strong>Lombok</strong> can help reduce the amount of boilerplate, they still don’t provide the same level of simplicity as Records. Here’s a comparison:</p>
<ul>
<li><p><strong>Record</strong>: Automatically generates constructor, getters, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code>.</p>
</li>
<li><p><strong>DTO</strong>: Requires manual implementation or the use of tools like Lombok.</p>
</li>
</ul>
<h3 id="heading-data-representation">Data Representation</h3>
<p><strong>Records</strong> provide a <strong>compact and concise</strong> way of representing data. Since the declaration of a Record contains only the fields, the code is cleaner and easier to read. This makes it easier to maintain, especially in projects with a lot of data models.</p>
<p>For example:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Record: Clean and simple</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> record <span class="hljs-title">UserRecord</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, String email)</span> </span>{}
</code></pre>
<p>Compare this to a DTO, which typically has a lot more code:</p>
<pre><code class="lang-java"><span class="hljs-comment">// DTO: More verbose</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">private</span> String email;

    <span class="hljs-comment">// Constructor, Getters, Setters, toString, equals, hashCode...</span>
}
</code></pre>
<p>With Records, the intent is clearer: it’s just a data carrier with no extra behavior, whereas DTOs can easily become cluttered with boilerplate or additional logic.</p>
<h3 id="heading-customization">Customization</h3>
<p>One area where <strong>DTOs</strong> have an advantage is in <strong>customization</strong>. DTOs allow you to add custom logic, such as data validation, transformation methods, or even business logic if needed (although this is generally discouraged in pure DTOs). For example, you could add a validation method to ensure the email field follows a valid format.</p>
<p>With <strong>Records</strong>, customization is more limited. Since they are designed to be lightweight and immutable, you can’t easily add custom methods that modify internal state or perform complex logic. If your use case requires custom behavior or logic in your data objects, DTOs offer more flexibility.</p>
<p>Here’s a quick example of adding custom validation to a DTO:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> String email;

    <span class="hljs-comment">// Method to validate email format</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> email != <span class="hljs-keyword">null</span> &amp;&amp; email.contains(<span class="hljs-string">"@"</span>);
    }
}
</code></pre>
<p>With a <strong>Record</strong>, this level of customization would typically be handled outside the Record itself. Records focus strictly on carrying data, while logic like validation is expected to be handled elsewhere.</p>
<h3 id="heading-alignment-with-functional-programming">Alignment with Functional Programming</h3>
<p>One of the key principles of <strong>functional programming</strong> is immutability — the idea that data objects should not be changed after they are created. <strong>Records</strong> align more closely with functional programming principles because they are <strong>immutable by default</strong>. This makes them an ideal choice in systems that favor or adopt a functional programming style.</p>
<ul>
<li><p><strong>Records</strong>:</p>
<ul>
<li><p>Designed to be immutable, which aligns with functional programming's emphasis on creating data structures that cannot change state.</p>
</li>
<li><p>They promote a more declarative style, where you can pass around immutable data objects without side effects, making them predictable and easier to reason about.</p>
</li>
</ul>
</li>
</ul>
<p>In contrast, <strong>DTOs</strong> are traditionally <strong>mutable</strong> by nature. While it’s possible to make DTOs immutable (by avoiding setters and using final fields), it requires manual enforcement. DTOs often follow the <strong>object-oriented</strong> paradigm, where state changes are more common.</p>
<ul>
<li><p><strong>DTOs</strong>:</p>
<ul>
<li><p>More flexible in terms of mutability, which makes them better suited to imperative or object-oriented programming styles.</p>
</li>
<li><p>When used in their mutable form, DTOs can lead to side effects, which is generally discouraged in functional programming.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-when-to-use-dto-vs-record">When to Use DTO vs Record</h2>
<p>When deciding between using a <strong>DTO</strong> or a <strong>Record</strong>, the choice depends largely on your specific use case, project requirements, and the version of Java you're using. Below is a breakdown of when to use each:</p>
<h3 id="heading-when-to-use-dtos">When to Use DTOs</h3>
<ol>
<li><p><strong>When mutability is required</strong>:<br /> If your object’s data needs to be modified after creation, <strong>DTOs</strong> are the better choice. DTOs are typically mutable, allowing you to change the values of fields as needed. This is useful in scenarios where data is updated throughout the lifecycle of an object.</p>
<p> Example: In a web application, a form submission may initially create a <code>UserDTO</code> with some fields left blank. As the user updates their profile, the <code>UserDTO</code> may need to change accordingly.</p>
</li>
<li><p><strong>When additional behavior or validation logic is needed</strong>:<br /> DTOs are more flexible when it comes to adding custom behavior like validation, transformations, or additional methods. If your data object needs logic beyond simply carrying data (e.g., verifying an email format or sanitizing input), then a DTO is more suitable.</p>
<p> Example: Adding a method in <code>UserDTO</code> to validate the format of an email before passing it between layers of your application.</p>
</li>
<li><p><strong>Compatibility with older versions of Java (pre-Java 16)</strong>:<br /> If your project is running on a version of Java earlier than Java 16, you won’t be able to use Records. In these cases, you’ll need to use traditional DTOs or alternatives like Lombok to simplify the code.</p>
<p> Example: If your application must support Java 11 or Java 8, then Records are not an option, and you’ll stick with DTOs.</p>
</li>
</ol>
<h3 id="heading-when-to-use-records">When to Use Records</h3>
<ol>
<li><p><strong>When you need a concise, immutable data carrier</strong>:<br /> <strong>Records</strong> are ideal when you need a lightweight, immutable object to carry data. Since they automatically generate essential methods (constructor, getters, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code>), they offer a clean and efficient way to represent data.</p>
<p> Example: If you’re transferring data between services in a microservice architecture and don't need to modify the data, a <code>UserRecord</code> would be a perfect fit.</p>
</li>
<li><p><strong>For read-only data transfer between layers or services</strong>:<br /> If your application involves passing data around without the need to modify it, using a Record is a great choice. The immutability of Records ensures that the data remains consistent, making it suitable for cases like sending data from the database to a service layer or from one service to another.</p>
<p> Example: A Record might be used to send user data from a database layer to a REST controller in a web application.</p>
</li>
<li><p><strong>In modern Java applications (Java 16+)</strong>:<br /> If your project uses Java 16 or later, you can take full advantage of Records. They are designed to simplify data representation in modern Java applications and help reduce the boilerplate that comes with traditional DTOs.</p>
<p> Example: In a Java 17 web service, you might use Records for all your data transfer needs between different layers of your application to keep the codebase concise and maintainable.</p>
</li>
</ol>
<h2 id="heading-performance-considerations">Performance Considerations</h2>
<p>When comparing <strong>DTOs</strong> and <strong>Records</strong> in terms of performance, the differences are typically minimal, but there are a few important factors to consider:</p>
<h3 id="heading-memory-efficiency">Memory Efficiency</h3>
<p>Since <strong>Records</strong> are compact by design, they may consume slightly less memory than traditional <strong>DTOs</strong>. The key reason is that Records do not require the additional overhead of manually implementing getters, setters, <code>equals()</code>, <code>hashCode()</code>, and <code>toString()</code> methods. All of this is generated automatically by the Java compiler in a more optimized way, resulting in a smaller memory footprint.</p>
<p>For example:</p>
<ul>
<li><p>A <strong>DTO</strong> would need separate fields and methods for each operation (<code>getName()</code>, <code>setName()</code>, etc.).</p>
</li>
<li><p>A <strong>Record</strong> internally holds just the fields and automatically generates the necessary methods, potentially using fewer resources.</p>
</li>
</ul>
<h3 id="heading-immutability-and-thread-safety">Immutability and Thread-Safety</h3>
<p>The immutable nature of <strong>Records</strong> provides some inherent performance benefits, particularly in <strong>multi-threaded environments</strong>. Since Records are immutable, they don’t require synchronization or locking mechanisms when shared between threads. This can lead to better performance in scenarios where thread contention would normally degrade performance.</p>
<p>In contrast, if you use <strong>mutable DTOs</strong> in multi-threaded environments, you need to ensure thread safety, either by synchronizing access or using other mechanisms, which can introduce overhead and slow down the application.</p>
<h3 id="heading-garbage-collection">Garbage Collection</h3>
<p>Both DTOs and Records are plain Java objects (POJOs), so they are subject to the same garbage collection process. However, the <strong>concise nature of Records</strong> could lead to slightly faster garbage collection, as fewer objects are created or held in memory. This can contribute to improved performance in long-running applications or those handling large volumes of data objects.</p>
<h3 id="heading-cpu-overhead">CPU Overhead</h3>
<p>Since Records are auto-generated by the compiler and are optimized for performance, there may be slight <strong>CPU performance improvements</strong> in operations such as object creation, method invocation, and comparison (<code>equals()</code>, <code>hashCode()</code>). This is particularly true when comparing complex DTOs where developers might introduce inefficiencies in manually implemented methods. The uniformity and optimization of Records ensure that these operations are handled consistently and efficiently.</p>
<h3 id="heading-real-world-performance-impact">Real-World Performance Impact</h3>
<p>In practice, the <strong>performance differences</strong> between DTOs and Records will likely be <strong>small</strong> and often <strong>negligible</strong> for most applications. The compact nature of Records might lead to slight performance gains in some scenarios, but the actual impact would only be noticeable in applications with heavy data processing, high throughput, or those running in resource-constrained environments (e.g., mobile or IoT devices).</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this tutorial, we've explored the key differences between <strong>DTOs</strong> and <strong>Records</strong>, their respective use cases, and how they align with different programming paradigms like functional programming. While <strong>DTOs</strong> offer flexibility, mutability, and custom behavior, <strong>Records</strong> provide a concise and immutable way to model data, making them ideal for modern Java applications.</p>
<p>The decision to use a <strong>DTO</strong> or a <strong>Record</strong> ultimately depends on your specific requirements:</p>
<ul>
<li><p>If you need <strong>mutability</strong> or want to add custom logic, DTOs are a better fit.</p>
</li>
<li><p>If you prefer a <strong>compact, immutable structure</strong> and are working in Java 16 or later, <strong>Records</strong> offer a cleaner and more efficient option.</p>
</li>
</ul>
<p>Both approaches have their strengths, and understanding when to use each will help you write more efficient and maintainable Java code.</p>
]]></content:encoded></item><item><title><![CDATA[Simplify Your Writing Workflow with Table of Contents Generator]]></title><description><![CDATA[Organizing content for clarity and ease of navigation is essential in the digital age. Whether you're writing a comprehensive article, a well-structured table of contents (TOC) can significantly enhance the readability of your content. TOC Generator ...]]></description><link>https://blog.ashutoshkrris.in/simplify-your-writing-workflow-with-table-of-contents-generator</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/simplify-your-writing-workflow-with-table-of-contents-generator</guid><category><![CDATA[toc-generator]]></category><category><![CDATA[Table of Contents]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sat, 03 Aug 2024 10:55:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1722768424987/6b88ff26-d188-4990-a5ec-12f45f30b024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Organizing content for clarity and ease of navigation is essential in the digital age. Whether you're writing a comprehensive article, a well-structured table of contents (TOC) can significantly enhance the readability of your content. <a target="_blank" href="https://toc-generator.ashutoshkrris.in/">TOC Generator</a> makes generating TOCs effortless, helping you focus on content creation rather than formatting. This article will explain how this tool can assist you and guide you through the process.</p>
<h2 id="heading-why-use-a-table-of-contents"><strong>Why Use a Table of Contents?</strong></h2>
<ul>
<li><p><strong>Enhanced Navigation:</strong> TOCs allow readers to quickly jump to sections of interest.</p>
</li>
<li><p><strong>Improved Readability:</strong> A clear structure helps understand the document's flow.</p>
</li>
<li><p><strong>Better SEO:</strong> Well-organized content is more likely to rank higher in search engines.</p>
</li>
</ul>
<h2 id="heading-key-features-of-the-application"><strong>Key Features of the Application</strong></h2>
<ul>
<li><p><strong>Supports freeCodeCamp Draft Posts:</strong> Easily generate TOCs for your drafts using the platform's unique URL.</p>
</li>
<li><p><strong>Markdown Support:</strong> Quickly convert your Markdown headers into a clickable TOC.</p>
</li>
<li><p><strong>User-Friendly Interface:</strong> Simple and intuitive design for a seamless experience.</p>
</li>
</ul>
<p>Here's a demo of the application:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/P5_nhLBcgEk">https://youtu.be/P5_nhLBcgEk</a></div>
<p> </p>
<h2 id="heading-how-to-use-the-toc-generator-for-freecodecamp"><strong>How to Use the TOC Generator for freeCodeCamp</strong></h2>
<ol>
<li><p><strong>Access the Application</strong></p>
<ul>
<li>Visit the <a target="_blank" href="https://toc-generator.ashutoshkrris.in/">TOC Generator</a> website.</li>
</ul>
</li>
<li><p><strong>Select the Level</strong></p>
<ul>
<li>Choose the "Single Level" or "Multi-Level" as per your choice.</li>
</ul>
</li>
<li><p><strong>Enter the Preview URL</strong></p>
<ul>
<li><p>Input your Hashnode Preview URL. The placeholder will show an example URL format for guidance: <a target="_blank" href="https://preview.freecodecamp.org/66bf202fb513336e7843a932"><code>https://preview.freecodecamp.org/66bf202fb513336e7843a932</code></a>.<br />  Here's how you can get the preview URL:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723871746006/f1e83701-752a-47d3-a652-3207491c414c.gif" alt="Hashnode Preview URL" class="image--center mx-auto" /></p>
</li>
</ul>
</li>
<li><p><strong>Generate TOC</strong></p>
<ul>
<li>Click the "Generate TOC" button to create a structured TOC.</li>
</ul>
</li>
</ol>
<p>You can copy the generated TOC and paste it into your article wherever you want. Hashnode will automatically convert the Markdown to proper links.</p>
<p>Sample TOC with Single Level Headings:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723871529484/696684fb-63df-4fca-9f37-61a1cb656271.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-to-use-the-toc-generator-for-markdown"><strong>How to Use the TOC Generator for Markdown</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1722768509639/38ca5b0e-dde3-42ca-9b1d-527a897504f6.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Access the Markdown TOC Generator</strong></p>
<ul>
<li>Visit our <a target="_blank" href="https://toc-generator.ashutoshkrris.in/markdown">Markdown TOC Generator</a> page.</li>
</ul>
</li>
<li><p><strong>Enter Your Markdown Content</strong></p>
<ul>
<li>Paste or type your Markdown content into the provided textbox.</li>
</ul>
</li>
<li><p><strong>Generate TOC</strong></p>
<ul>
<li>Click "Generate TOC" to automatically generate the TOC based on your headers.</li>
</ul>
</li>
<li><p><strong>Copy the TOC</strong></p>
<ul>
<li>Use the "Copy" button to copy the TOC to your clipboard.</li>
</ul>
</li>
</ol>
<h2 id="heading-benefits-of-using-our-application"><strong>Benefits of Using Our Application</strong></h2>
<ul>
<li><p><strong>Time-Saving:</strong> Quickly generate TOCs without manual formatting.</p>
</li>
<li><p><strong>Consistency:</strong> Ensure your TOC is always formatted correctly.</p>
</li>
<li><p><strong>Versatility:</strong> Suitable for various platforms and content types.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>My Table of Contents Generator is designed to streamline the process of organizing your content, making it easier for your readers to navigate and understand. Whether you're a freeCodeCamp contributor or a Markdown enthusiast, this tool can enhance your workflow and improve the presentation of your work. Try it out today and see how it can simplify your content creation process!</p>
]]></content:encoded></item><item><title><![CDATA[Comparable vs Comparator Explained in Java]]></title><description><![CDATA[Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collection...]]></description><link>https://blog.ashutoshkrris.in/comparable-vs-comparator-explained-in-java</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/comparable-vs-comparator-explained-in-java</guid><category><![CDATA[Java]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[coding]]></category><category><![CDATA[interview]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sat, 20 Jul 2024 20:01:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721505697717/cf92ee5b-1fd8-4a01-aff1-780ce13dbc23.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collections of data. For instance, you can quickly sort an array of integers or a list of strings using methods like <code>Arrays.sort()</code> and <code>Collections.sort()</code>.</p>
<p>However, when it comes to sorting custom objects, such as instances of user-defined classes, the built-in sorting methods fall short. These methods don't know how to order objects based on custom criteria. This is where Java's <code>Comparable</code> and <code>Comparator</code> interfaces come into play, allowing developers to define and implement custom sorting logic tailored to specific requirements.</p>
<p>In this blog post, we'll explore how to use the <code>Comparable</code> and <code>Comparator</code> interfaces to sort custom objects in Java. I'll provide examples to illustrate the differences and use cases for each approach, helping you master custom sorting in your Java applications.</p>
<h2 id="heading-sorting-methods-for-primitive-types">Sorting Methods for Primitive Types</h2>
<p>Java provides a variety of built-in sorting methods that make it easy to sort primitive data types. These methods are highly optimized and efficient, allowing you to sort arrays and collections with minimal code. For primitive types, such as integers, floating-point numbers, and characters, the <code>Arrays.sort()</code> method is commonly used.</p>
<h3 id="heading-arrayssort">Arrays.sort()</h3>
<p>The <code>Arrays.sort()</code> method sorts the specified array into ascending numerical order. This method uses a Dual-Pivot Quicksort algorithm, which is faster and more efficient for most data sets.</p>
<p>Let's look at an example of sorting an array of integers and characters using <code>Arrays.sort()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.Arrays;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PrimitiveSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">int</span>[] numbers = { <span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span> };
        System.out.println(<span class="hljs-string">"Original array: "</span> + Arrays.toString(numbers));

        Arrays.sort(numbers);
        System.out.println(<span class="hljs-string">"Sorted array: "</span> + Arrays.toString(numbers));

        <span class="hljs-keyword">char</span>[] characters = { <span class="hljs-string">'o'</span>, <span class="hljs-string">'i'</span>, <span class="hljs-string">'e'</span>, <span class="hljs-string">'u'</span>, <span class="hljs-string">'a'</span> };
        System.out.println(<span class="hljs-string">"Original array: "</span> + Arrays.toString(characters));

        Arrays.sort(characters);
        System.out.println(<span class="hljs-string">"Sorted array: "</span> + Arrays.toString(characters));
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original array: [5, 3, 8, 2, 1]
Sorted array: [1, 2, 3, 5, 8]
Original array: [o, i, e, u, a]
Sorted array: [a, e, i, o, u]
</code></pre>
<h3 id="heading-collectionssort">Collections.sort()</h3>
<p>The <code>Collections.sort()</code> method is used to sort collections such as <code>ArrayList</code>. This method is also based on the natural ordering of the elements or a custom comparator.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collections;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CollectionsSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        ArrayList&lt;String&gt; wordsList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        wordsList.add(<span class="hljs-string">"banana"</span>);
        wordsList.add(<span class="hljs-string">"apple"</span>);
        wordsList.add(<span class="hljs-string">"cherry"</span>);
        wordsList.add(<span class="hljs-string">"date"</span>);
        System.out.println(<span class="hljs-string">"Original list: "</span> + wordsList);

        Collections.sort(wordsList);
        System.out.println(<span class="hljs-string">"Sorted list: "</span> + wordsList);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-plaintext">Original list: [banana, apple, cherry, date]
Sorted list: [apple, banana, cherry, date]
</code></pre>
<h3 id="heading-limitations-with-custom-classes">Limitations with Custom Classes</h3>
<p>While Java's built-in sorting methods, such as <code>Arrays.sort()</code> and <code>Collections.sort()</code>, are powerful and efficient for sorting primitive types and objects with natural ordering (like <code>String</code>), they fall short when it comes to sorting custom objects. These methods do not inherently know how to order user-defined objects because there is no natural way for them to compare these objects.</p>
<p>For example, consider a simple <code>Person</code> class that has <code>name</code>, <code>age</code>, and <code>weight</code> attributes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }
}
</code></pre>
<p>If we try to sort a list of <code>Person</code> objects using <code>Arrays.sort()</code> or <code>Collections.sort()</code>, we will encounter a compilation error because these methods do not know how to compare <code>Person</code> objects:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Person&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people);
        System.out.println(<span class="hljs-string">"Sorted people list: "</span> + people);
    }
}
</code></pre>
<p>Compilation Error:</p>
<pre><code class="lang-bash">java: no suitable method found <span class="hljs-keyword">for</span> sort(java.util.List&lt;tutorial.Person&gt;)
    method java.util.Collections.&lt;T&gt;sort(java.util.List&lt;T&gt;) is not applicable
      (inference variable T has incompatible bounds
        equality constraints: tutorial.Person
        lower bounds: java.lang.Comparable&lt;? super T&gt;)
    method java.util.Collections.&lt;T&gt;sort(java.util.List&lt;T&gt;,java.util.Comparator&lt;? super T&gt;) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ <span class="hljs-keyword">in</span> length))
</code></pre>
<p>The error occurs because the <code>Person</code> class does not implement the <code>Comparable</code> interface, and there is no way for the sorting method to know how to compare two <code>Person</code> objects.</p>
<p>To sort custom objects like <code>Person</code>, we need to provide a way to compare these objects. Java offers two main approaches to achieve this:</p>
<ol>
<li><p>Implementing the <code>Comparable</code> Interface: This allows a class to define its natural ordering by implementing the <code>compareTo</code> method.</p>
</li>
<li><p>Using the <code>Comparator</code> Interface: This allows us to create separate classes or lambda expressions to define multiple ways of comparing objects.</p>
</li>
</ol>
<p>We will explore both approaches in the upcoming sections, starting with the <code>Comparable</code> interface.</p>
<h2 id="heading-comparable-interface">Comparable Interface</h2>
<p>Java provides a <code>Comparable</code> interface to define a natural ordering for objects of a user-defined class. By implementing the <code>Comparable</code> interface, a class can provide a single natural ordering that can be used to sort its instances. This is particularly useful when you need a default way to compare and sort objects.</p>
<h3 id="heading-overview">Overview</h3>
<p>The <code>Comparable</code> interface contains a single method, <code>compareTo()</code>, which compares the current object with the specified object for order. The method returns:</p>
<ul>
<li><p>A negative integer if the current object is less than the specified object.</p>
</li>
<li><p>Zero if the current object is equal to the specified object.</p>
</li>
<li><p>A positive integer if the current object is greater than the specified object.</p>
</li>
</ul>
<h3 id="heading-how-comparable-allows-for-a-single-natural-ordering-of-objects">How Comparable Allows for a Single Natural Ordering of Objects</h3>
<p>By implementing the <code>Comparable</code> interface, a class can ensure that its objects have a natural ordering. This allows the objects to be sorted using methods like <code>Arrays.sort()</code> or <code>Collections.sort()</code> without the need for a separate comparator.</p>
<p>Let's implement the <code>Comparable</code> interface in a new <code>PersonV2</code> class, comparing by age.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonV2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparable</span>&lt;<span class="hljs-title">PersonV2</span>&gt; </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PersonV2</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"PersonV2 [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compareTo</span><span class="hljs-params">(PersonV2 other)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.age - other.age;
    }
}
</code></pre>
<p>In this implementation, the <code>compareTo()</code> method compares the <code>age</code> attribute of the current <code>PersonV2</code> object with the <code>age</code> attribute of the specified <code>PersonV2</code> object by subtracting one age from the other. By using the expression <code>this.age - other.age</code>, we’re effectively implementing this logic as follows:</p>
<ul>
<li><p>If <code>this.age</code> is less than <code>other.age</code>, the result will be negative.</p>
</li>
<li><p>If <code>this.age</code> is equal to <code>other.age</code>, the result will be zero.</p>
</li>
<li><p>If <code>this.age</code> is greater than <code>other.age</code>, the result will be positive.</p>
</li>
</ul>
<blockquote>
<p>Note: We can also use <code>Integer.compare(this.age, other.age)</code> instead of performing the arithmetic operation manually.</p>
</blockquote>
<p>Now that the <code>PersonV2</code> class implements the <code>Comparable</code> interface, we can sort a list of <code>PersonV2</code> objects using <code>Collections.sort()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSortingV2</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;PersonV2&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people);
        System.out.println(<span class="hljs-string">"Sorted people list: "</span> + people);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original people list: [PersonV2 [name=Alice, age=30, weight=65.5 kgs], PersonV2 [name=Bob, age=25, weight=75.0 kgs], PersonV2 [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list: [PersonV2 [name=Bob, age=25, weight=75.0 kgs], PersonV2 [name=Alice, age=30, weight=65.5 kgs], PersonV2 [name=Charlie, age=35, weight=80.0 kgs]]
</code></pre>
<p>In this example, the <code>PersonV2</code> objects are sorted in ascending order of age using the <code>Collections.sort()</code> method, which relies on the natural ordering defined by the <code>compareTo()</code> method in the <code>PersonV2</code> class.</p>
<h3 id="heading-limitations-of-comparable">Limitations of Comparable</h3>
<p>While the <code>Comparable</code> interface provides a way to define a natural ordering for objects, it has several limitations that can restrict its use in practical applications. Understanding these limitations can help us determine when to use other mechanisms, such as the <code>Comparator</code> interface, to achieve more flexible sorting.</p>
<ul>
<li><p><strong>Single Natural Ordering</strong>: The primary limitation of <code>Comparable</code> is that it allows only one natural ordering for the objects of a class. When you implement <code>Comparable</code>, you define a single way to compare objects, which is used whenever the objects are sorted or compared. This can be restrictive if you need to sort objects in multiple ways.</p>
</li>
<li><p><strong>Inflexibility</strong>: If you need to sort objects by different attributes or in different orders, you will have to modify the class or create new implementations of <code>Comparable</code>. This inflexibility can lead to a proliferation of comparison methods and can make the code harder to maintain.</p>
</li>
<li><p><strong>Non-Adaptable</strong>: Once a class implements <code>Comparable</code>, the natural ordering is fixed and cannot be easily changed. For instance, if your <code>PersonV2</code> class initially sorts by age but later you need to sort by weight or name, you have to either change the <code>compareTo()</code> method or create a new version of the class.</p>
</li>
</ul>
<p>This is where the <code>Comparator</code> interface comes into play. To define multiple ways of comparing objects, we can use the <code>Comparator</code> interface, which we will explore in the next section.</p>
<h2 id="heading-comparator-interface">Comparator Interface</h2>
<p>The <code>Comparator</code> interface in Java provides a way to define multiple ways to compare and sort objects. Unlike the <code>Comparable</code> interface, which allows only a single natural ordering, <code>Comparator</code> is designed to offer flexibility by allowing multiple sorting strategies. This makes it particularly useful for scenarios where objects need to be sorted in different ways.</p>
<h3 id="heading-overview-1">Overview</h3>
<p>The <code>Comparator</code> interface defines a single method, <code>compare()</code>, which compares two objects and returns:</p>
<ul>
<li><p>A negative integer if the first object is less than the second object.</p>
</li>
<li><p>Zero if the first object is equal to the second object.</p>
</li>
<li><p>A positive integer if the first object is greater than the second object.</p>
</li>
</ul>
<p>This method provides a way to define custom ordering for objects without modifying the class itself.</p>
<h3 id="heading-how-comparator-allows-for-multiple-ways-of-ordering-objects">How Comparator Allows for Multiple Ways of Ordering Objects</h3>
<p>The <code>Comparator</code> interface allows you to create multiple <code>Comparator</code> instances, each defining a different ordering for objects. This flexibility means you can sort objects by various attributes or in different orders without altering the object's class.</p>
<p>Let's implement multiple <code>Comparator</code> instances for the <code>Person</code> class. We'll define comparators for sorting by name, by age, and by weight. First, we need to update the <code>Person</code> class to include getters and ensure that attributes are accessible.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getWeight</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }
}
</code></pre>
<h4 id="heading-comparator-by-name"><strong>Comparator by Name</strong></h4>
<p>This comparator sorts <code>Person</code> objects alphabetically by their <code>name</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonNameComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> p1.getName().compareTo(p2.getName());
    }
}
</code></pre>
<h4 id="heading-comparator-by-age">Comparator by Age</h4>
<p>This comparator sorts <code>Person</code> objects by their <code>age</code>, in ascending order.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonAgeComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> p1.getAge() - p2.getAge();
    }
}
</code></pre>
<h4 id="heading-comparator-by-weight">Comparator by Weight</h4>
<p>This comparator sorts <code>Person</code> objects by their <code>weight</code>, in ascending order.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonWeightComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>) (p1.getWeight() - p2.getWeight());
    }
}
</code></pre>
<p>Now, here’s how you can use these <code>Comparator</code> instances to sort a list of <code>Person</code> objects:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> tutorial.comparator.PersonAgeComparator;
<span class="hljs-keyword">import</span> tutorial.comparator.PersonNameComparator;
<span class="hljs-keyword">import</span> tutorial.comparator.PersonWeightComparator;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSortingV3</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Person&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonNameComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by name: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonAgeComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by age: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonWeightComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by weight: "</span> + people);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original people list: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by name: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by age: [Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by weight: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
</code></pre>
<p>In this example, the <code>Comparator</code> instances allow sorting the <code>Person</code> objects by different attributes: name, age, and weight. This demonstrates how the <code>Comparator</code> interface enables flexible and versatile sorting strategies for a class.</p>
<h2 id="heading-comparable-vs-comparator">Comparable vs Comparator</h2>
<p>When sorting objects in Java, you have two primary options: the <code>Comparable</code> and <code>Comparator</code> interfaces. Understanding the differences between these two interfaces can help you choose the right approach for your needs. Please note that this is also a <strong>very important interview question</strong>.</p>
<h3 id="heading-comparison">Comparison</h3>
<p>Here’s a table comparing and contrasting the <code>Comparable</code> and <code>Comparator</code> interfaces in Java:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Comparable</td><td>Comparator</td></tr>
</thead>
<tbody>
<tr>
<td>Definition</td><td>Provides a single, natural ordering for objects</td><td>Provides multiple ways to compare objects</td></tr>
<tr>
<td>Method</td><td>compareTo(T o)</td><td>compare(T o1, T o2)</td></tr>
<tr>
<td>Implementation</td><td>Implemented within the class itself</td><td>Implemented outside the class</td></tr>
<tr>
<td>Sorting Criteria</td><td>One default natural ordering</td><td>Multiple sorting criteria</td></tr>
<tr>
<td>Flexibility</td><td>Limited to one way of comparing objects</td><td>Flexible; multiple comparators can be defined</td></tr>
<tr>
<td>Class Modification</td><td>Requires modifying the class to implement <code>Comparable</code></td><td>Does not require modifying the class</td></tr>
<tr>
<td>Use Case</td><td>Use when there is a clear, natural ordering (e.g., sorting employees by ID)</td><td>Use when different sorting orders are needed or when you cannot modify the class</td></tr>
</tbody>
</table>
</div><h3 id="heading-benefits-and-drawbacks-of-each-approach">Benefits and Drawbacks of Each Approach</h3>
<h4 id="heading-comparable"><strong>Comparable</strong></h4>
<ul>
<li><p><strong>Benefits</strong>:</p>
<ul>
<li><p><strong>Simplicity</strong>: Provides a default sorting order that is easy to implement and use.</p>
</li>
<li><p><strong>Built-in</strong>: The natural ordering is part of the class itself, so it is always available and used by default in sorting methods.</p>
</li>
</ul>
</li>
<li><p><strong>Drawbacks</strong>:</p>
<ul>
<li><p><strong>Single Ordering</strong>: Can only define one way to compare objects. If different sorting orders are needed, the class must be modified or additional <code>Comparator</code> instances must be used.</p>
</li>
<li><p><strong>Class Modification</strong>: Requires altering the class to implement <code>Comparable</code>, which might not be feasible if the class is part of a library or if its natural ordering is not clear.</p>
</li>
</ul>
</li>
</ul>
<h4 id="heading-comparator"><strong>Comparator</strong></h4>
<ul>
<li><p><strong>Benefits</strong>:</p>
<ul>
<li><p><strong>Flexibility</strong>: Allows for multiple sorting orders and criteria, which can be defined externally and used as needed.</p>
</li>
<li><p><strong>Non-invasive</strong>: Does not require modification of the class itself, making it suitable for classes you do not control or when you need different sorting options.</p>
</li>
</ul>
</li>
<li><p><strong>Drawbacks</strong>:</p>
<ul>
<li><p><strong>Complexity</strong>: Requires creating and managing multiple <code>Comparator</code> instances, which can add complexity to the code.</p>
</li>
<li><p><strong>Overhead</strong>: Might introduce additional overhead if many comparators are used, especially if they are created on the fly.</p>
</li>
</ul>
</li>
</ul>
<p>In summary, <code>Comparable</code> is best used when a class has a natural ordering that makes sense for most use cases. <code>Comparator</code>, on the other hand, provides flexibility for sorting by multiple criteria and is useful when the class does not have a natural ordering or when different sorting orders are needed. Choosing between <code>Comparable</code> and <code>Comparator</code> depends on your specific sorting needs and whether you need a single default order or multiple flexible sorting options.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Understanding and utilizing both <code>Comparable</code> and <code>Comparator</code> can significantly enhance your ability to manage and manipulate object collections in Java. By applying these concepts, you can create more flexible and powerful sorting mechanisms.</p>
<p>To solidify your understanding, try implementing both <code>Comparable</code> and <code>Comparator</code> in real-world scenarios. Experiment with different classes and sorting criteria to see how each approach works in practice.</p>
<p><strong>Links to Official Java Documentation</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html">Java Comparable Interface</a></p>
</li>
<li><p><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html">Java Comparator Interface</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Implementing Instant Search with Flask and HTMX]]></title><description><![CDATA[Introduction
Instant search is a feature that shows search results as users type their query. Instead of waiting for a full page to reload or submitting a form, results appear instantly, allowing users to find what they are looking for more quickly. ...]]></description><link>https://blog.ashutoshkrris.in/implementing-instant-search-with-flask-and-htmx</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/implementing-instant-search-with-flask-and-htmx</guid><category><![CDATA[Python]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[htmx]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[beginner]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[projects]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Thu, 18 Jul 2024 17:38:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1721324236154/48518f00-c61e-4723-bcc9-e81533e14e9c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Instant search is a feature that shows search results as users type their query. Instead of waiting for a full page to reload or submitting a form, results appear instantly, allowing users to find what they are looking for more quickly. For example, when you start typing in a search box, suggestions or matching items will appear immediately, making the process smoother and more efficient.</p>
<p>In this tutorial, we will learn how to create a simple instant search feature using Flask and HTMX. This will help you build interactive web applications with a better user experience.</p>
<h3 id="heading-why-use-instant-search"><strong>Why Use Instant Search?</strong></h3>
<ul>
<li><p><strong>Speed</strong>: Users get immediate feedback, which helps them refine their search.</p>
</li>
<li><p><strong>Convenience</strong>: It reduces the number of clicks and page loads, leading to a more seamless experience.</p>
</li>
<li><p><strong>Engagement</strong>: Users are more likely to stay on your site if they can find what they need easily.</p>
</li>
</ul>
<h3 id="heading-technologies-used"><strong>Technologies Used</strong></h3>
<p>To implement this instant search feature, we will use two main technologies:</p>
<ul>
<li><p><strong>Flask</strong>: <a target="_blank" href="https://blog.ashutoshkrris.in/getting-started-with-flask">Flask</a> is a popular web framework for Python. It is simple and lightweight, making it easy to set up and start building web applications quickly. Flask allows us to create routes, handle requests, and serve HTML templates with minimal setup.</p>
</li>
<li><p><strong>HTMX</strong>: This is a powerful JavaScript library that allows us to create dynamic web pages without having to write a lot of JavaScript code. With HTMX, we can update parts of a page based on user actions, like typing in a search box. It makes it easy to load data from the server and display it on the page without a full reload.</p>
</li>
</ul>
<h2 id="heading-setting-up-the-environment">Setting Up the Environment</h2>
<p>In this section, we will set up the environment for our Flask project, including installing the necessary packages and organizing the project structure.</p>
<h4 id="heading-1-installing-flask-and-htmx">1. Installing Flask and HTMX</h4>
<p>First, you need to install Flask, Flask-SQLAlchemy, and Flask-Migrate. You can do this using pip. Open your terminal and run:</p>
<pre><code class="lang-bash">pip install Flask Flask-SQLAlchemy Flask-Migrate
</code></pre>
<p>For HTMX, we will include it in our HTML template directly from a CDN.</p>
<h4 id="heading-2-creating-a-virtual-environment">2. Creating a Virtual Environment</h4>
<p>It's a good practice to create a virtual environment for your projects to manage dependencies. Here's how to create one:</p>
<pre><code class="lang-bash">python -m venv venv
</code></pre>
<p>Next, activate the environment:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># On Windows</span>
venv\Scripts\activate

<span class="hljs-comment"># On macOS/Linux</span>
<span class="hljs-built_in">source</span> venv/bin/activate
</code></pre>
<h4 id="heading-3-setting-up-the-project-structure">3. Setting Up the Project Structure</h4>
<p>Now, set up your project structure as follows:</p>
<pre><code class="lang-bash">my_flask_app/
├── core/
│   ├── __init__.py
│   ├── models.py
│   └── routes.py
├── config.py
└── main.py
</code></pre>
<p>Let us start with creating the first file - <code>core/__init__.py</code>. This file is the initialization script for the core module of our Flask application. It sets up the Flask app instance and configures it using the settings from the <code>DevelopmentConfig</code> class, and initialize the database and migration system.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_sqlalchemy <span class="hljs-keyword">import</span> SQLAlchemy
<span class="hljs-keyword">from</span> flask_migrate <span class="hljs-keyword">import</span> Migrate
<span class="hljs-keyword">from</span> config <span class="hljs-keyword">import</span> DevelopmentConfig

<span class="hljs-comment"># Create the Flask app instance</span>
app = Flask(__name__)

<span class="hljs-comment"># Load configuration from DevelopmentConfig</span>
app.config.from_object(DevelopmentConfig)

<span class="hljs-comment"># Initialize SQLAlchemy with the app instance</span>
db = SQLAlchemy(app)

<span class="hljs-comment"># Initialize Flask-Migrate with the app instance and database</span>
migrate = Migrate(app, db)

<span class="hljs-comment"># Import routes to register them with the app</span>
<span class="hljs-keyword">from</span> core <span class="hljs-keyword">import</span> routes
</code></pre>
<p>Next, we will create the <code>config.py</code> file from where we imported the <code>DevelopmentConfig</code> class. This file contains configuration settings for different environments (development, testing, production). These settings help manage different behaviors and configurations based on where your app is running.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>(<span class="hljs-params">object</span>):</span>
    DEBUG = <span class="hljs-literal">False</span>
    TESTING = <span class="hljs-literal">False</span>
    CSRF_ENABLED = <span class="hljs-literal">True</span>
    SECRET_KEY = <span class="hljs-string">"guess-me"</span>
    SQLALCHEMY_DATABASE_URI = <span class="hljs-string">"sqlite:///db.sqlite"</span>
    SQLALCHEMY_TRACK_MODIFICATIONS = <span class="hljs-literal">False</span>
    BCRYPT_LOG_ROUNDS = <span class="hljs-number">13</span>
    WTF_CSRF_ENABLED = <span class="hljs-literal">True</span>
    DEBUG_TB_ENABLED = <span class="hljs-literal">False</span>
    DEBUG_TB_INTERCEPT_REDIRECTS = <span class="hljs-literal">False</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DevelopmentConfig</span>(<span class="hljs-params">Config</span>):</span>
    DEVELOPMENT = <span class="hljs-literal">True</span>
    DEBUG = <span class="hljs-literal">True</span>
    WTF_CSRF_ENABLED = <span class="hljs-literal">False</span>
    DEBUG_TB_ENABLED = <span class="hljs-literal">True</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestingConfig</span>(<span class="hljs-params">Config</span>):</span>
    TESTING = <span class="hljs-literal">True</span>
    DEBUG = <span class="hljs-literal">True</span>
    SQLALCHEMY_DATABASE_URI = <span class="hljs-string">"sqlite:///testdb.sqlite"</span>
    BCRYPT_LOG_ROUNDS = <span class="hljs-number">1</span>
    WTF_CSRF_ENABLED = <span class="hljs-literal">False</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductionConfig</span>(<span class="hljs-params">Config</span>):</span>
    DEBUG = <span class="hljs-literal">False</span>
    DEBUG_TB_ENABLED = <span class="hljs-literal">False</span>
</code></pre>
<ul>
<li><p><code>Config</code>: The base configuration class with default settings.</p>
</li>
<li><p><code>DevelopmentConfig</code>: Inherits from <code>Config</code> and overrides development settings.</p>
</li>
<li><p><code>TestingConfig</code>: Inherits from <code>Config</code> and overrides settings for testing.</p>
</li>
<li><p><code>ProductionConfig</code>: Inherits from <code>Config</code> and overrides production settings.</p>
</li>
</ul>
<p>Finally, we will create the <code>main.py</code> file. This is the entry point of our application. When we run this file, it starts the Flask web server.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> core <span class="hljs-keyword">import</span> app

<span class="hljs-comment"># Start the Flask app</span>
<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    app.run(debug=<span class="hljs-literal">True</span>)
</code></pre>
<ul>
<li><p><code>if __name__ == '__main__'</code>: This ensures the Flask app runs only if the script is executed directly (not imported as a module).</p>
</li>
<li><p><code>app.run(debug=True)</code>: Starts the Flask development server with debug mode enabled, which provides detailed error messages and auto-reloading.</p>
</li>
</ul>
<p>Now that you understand the project files, we can proceed with implementing the instant search functionality. This will involve creating the models and search route, setting up the HTMX-powered front-end, and connecting everything to fetch and display search results dynamically.</p>
<h2 id="heading-setting-up-the-database">Setting up the Database</h2>
<p>In this section, we will set up the database for our Flask application. We will use SQLite for simplicity. We will create a model for the data we want to search and seed the database with sample data.</p>
<p>SQLite is a lightweight, disk-based database that doesn’t require a separate server process. It's an excellent choice for development and small projects because it is easy to set up and use.</p>
<h3 id="heading-creating-model-for-the-data-to-be-searched">Creating Model for the Data to Be Searched</h3>
<p>We will create a <code>Book</code> model to represent the data in our database. This model will include fields like the book title and author.</p>
<p>Let's create the <code>core/models.py</code> file and add the model there:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> core <span class="hljs-keyword">import</span> db

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span>(<span class="hljs-params">db.Model</span>):</span>
    id = db.Column(db.Integer, primary_key=<span class="hljs-literal">True</span>)
    title = db.Column(db.String(<span class="hljs-number">100</span>), nullable=<span class="hljs-literal">False</span>)
    author = db.Column(db.String(<span class="hljs-number">100</span>), nullable=<span class="hljs-literal">False</span>)
</code></pre>
<h3 id="heading-applying-migrations-using-flask-migrate">Applying Migrations Using Flask-Migrate</h3>
<p>Before we can seed our database, we need to set up database migrations using Flask-Migrate. This tool helps us manage database changes, such as creating tables and altering schemas, systematically.</p>
<p>Initialize the migrations folder by running the following command in your project directory:</p>
<pre><code class="lang-bash">flask db init
</code></pre>
<p>This command creates a <code>migrations</code> directory in our project, which will store migration scripts.</p>
<p>Generate a migration script that creates the necessary database tables based on your models:</p>
<pre><code class="lang-bash">flask db migrate -m <span class="hljs-string">"Initial migration"</span>
</code></pre>
<p>This command scans your models and generates a new migration script in the <code>migrations</code> folder.</p>
<p>Apply the migration to create the tables in your database:</p>
<pre><code class="lang-bash">flask db upgrade
</code></pre>
<p>This command executes the migration script, creating the tables defined by your models in the database. Post this step, you will see an <code>instance/db.sqlite</code> file created.</p>
<h3 id="heading-seeding-data-into-our-database">Seeding Data Into Our Database</h3>
<p>Now that we have set up the database and applied the migration, we can proceed with seeding the database. Create a file named <code>seeder.py</code> with the following content:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> csv
<span class="hljs-keyword">from</span> sqlalchemy.exc <span class="hljs-keyword">import</span> IntegrityError

<span class="hljs-keyword">from</span> core <span class="hljs-keyword">import</span> db, app
<span class="hljs-keyword">from</span> core.models <span class="hljs-keyword">import</span> Book


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">seed_data</span>():</span>
    <span class="hljs-keyword">with</span> app.app_context():
        <span class="hljs-comment"># Open the CSV file</span>
        <span class="hljs-keyword">with</span> open(<span class="hljs-string">"data.csv"</span>, newline=<span class="hljs-string">''</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> csvfile:
            reader = csv.DictReader(csvfile)

            <span class="hljs-comment"># Iterate over the rows in the CSV file</span>
            <span class="hljs-keyword">for</span> row <span class="hljs-keyword">in</span> reader:
                <span class="hljs-comment"># Create a new Book instance</span>
                book = Book(
                    title=row[<span class="hljs-string">'Book Name'</span>],
                    author=row[<span class="hljs-string">'Author Name'</span>]
                )

                <span class="hljs-comment"># Add the book to the session</span>
                db.session.add(book)

            <span class="hljs-keyword">try</span>:
                <span class="hljs-comment"># Commit the session to write the books to the database</span>
                db.session.commit()
                print(<span class="hljs-string">"Books added successfully."</span>)
            <span class="hljs-keyword">except</span> IntegrityError <span class="hljs-keyword">as</span> e:
                db.session.rollback()
                print(<span class="hljs-string">f"Error occurred: <span class="hljs-subst">{e}</span>"</span>)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    seed_data()
</code></pre>
<p>The seeder script is responsible for populating the database with initial data. This is useful for testing and development purposes, allowing you to work with a set of sample data. This script reads data from <code>data.csv</code>, and processes it to insert it into the database.</p>
<blockquote>
<p>Note: You can download the <a target="_blank" href="https://github.com/ashutoshkrris/instant-search-with-flask-htmx/blob/main/data.csv">data.csv</a> file from here.</p>
</blockquote>
<p>To use this script, ensure your <code>data.csv</code> file exists in the same directory as <a target="_blank" href="http://seeder.py"><code>seeder.py</code></a>. Run the script using Python:</p>
<pre><code class="lang-bash">python seeder.py
</code></pre>
<h2 id="heading-setting-up-basic-routing-and-html">Setting Up Basic Routing and HTML</h2>
<p>In this section, we'll set up a basic route in Flask to serve an index page (<code>index.html</code>) where users can search and display books.</p>
<h3 id="heading-setting-up-flask-route">Setting Up Flask Route</h3>
<p>Let's set up a Flask route (<code>/</code>) to render an <code>index.html</code> template and display books. For that, create a <code>core/routes.py</code> file and add the following route:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> render_template
<span class="hljs-keyword">from</span> core <span class="hljs-keyword">import</span> app
<span class="hljs-keyword">from</span> core.models <span class="hljs-keyword">import</span> Book

<span class="hljs-meta">@app.route('/')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>():</span>
    <span class="hljs-comment"># Fetch the first 20 books to display by default</span>
    books = Book.query.limit(<span class="hljs-number">20</span>).all()
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"index.html"</span>, books=books)
</code></pre>
<p>The Flask application handles routing through the <code>@app.route('/')</code> decorator, which directs requests to the root URL (<code>/</code>). When a user visits the homepage, the <code>index()</code> function is invoked. Inside this function, we query the <code>Book</code> model using SQLAlchemy to fetch the first 20 books from the database. These books are then passed as a parameter (<code>books</code>) to the <code>render_template</code> function, which renders the <code>index.html</code> template.</p>
<h3 id="heading-creating-the-indexhtml-template">Creating the <code>index.html</code> Template</h3>
<p>Create a file named <code>index.html</code> inside a <code>templates</code> directory in your project. The <code>templates</code> directory will lie in the <code>core</code> package. This file will contain the HTML structure for our book search page.</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Book Search<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"section"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"columns"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"column is-one-third is-offset-one-third"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"input"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"query"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table is-fullwidth"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>ID<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Book Title<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Book Author<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"results"</span>&gt;</span>
        {% for book in books %}
        <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ book.id }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ book.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ book.author }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
        {% endfor %}
      <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This HTML file uses the Bulma CSS framework for styling and includes elements such as an input field for user searches and a table to display book details fetched from the database.</p>
<p>The <code>index.html</code> template utilizes Jinja2 templating to dynamically populate the table rows (<code>&lt;tr&gt;</code>) with book data retrieved from the Flask backend. Each book's ID, title, and author are displayed in the table rows using <code>{{</code><a target="_blank" href="http://book.id"><code>book.id</code></a><code>}}</code>, <code>{{ book.title }}</code>, and <code>{{</code><a target="_blank" href="http://book.author"><code>book.author</code></a><code>}}</code> respectively.</p>
<h3 id="heading-running-the-application">Running the application</h3>
<p>Let's run the application using the following command:</p>
<pre><code class="lang-bash">flask run
</code></pre>
<p>Once your application is up and running, this is how it will look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1721316465728/d5037fd3-f49b-4c59-993c-4ff7c23cabef.png" alt="Book Search Application Home Page" class="image--center mx-auto" /></p>
<h2 id="heading-adding-htmx-for-instant-search">Adding HTMX for Instant Search</h2>
<p>Finally, we will add HTMX to enhance our Flask application with dynamic search capabilities. For this, we'll introduce a new route and modify existing HTML templates.</p>
<h3 id="heading-creating-the-search-route">Creating the Search Route</h3>
<p>First, create a new route <code>/search</code> in your Flask application to handle book searches based on user input:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> render_template, request
<span class="hljs-keyword">from</span> core <span class="hljs-keyword">import</span> app
<span class="hljs-keyword">from</span> core.models <span class="hljs-keyword">import</span> Book

<span class="hljs-meta">@app.route('/search')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>():</span>
    query = request.args.get(<span class="hljs-string">"query"</span>)
    <span class="hljs-keyword">if</span> query:
        results = Book.query.filter(Book.title.ilike(<span class="hljs-string">f"%<span class="hljs-subst">{query}</span>%"</span>) | Book.author.ilike(<span class="hljs-string">f"%<span class="hljs-subst">{query}</span>%"</span>)).limit(<span class="hljs-number">10</span>).all()
    <span class="hljs-keyword">else</span>:
        results = Book.query.limit(<span class="hljs-number">20</span>).all()
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"search_results.html"</span>, results=results)
</code></pre>
<p>This route listens for GET requests to <code>/search</code>. It retrieves the search query from the URL parameter using <code>request.args.get("query")</code>. If a <code>query</code> parameter is present, it uses SQLAlchemy's <code>ilike</code> method to perform a case-insensitive search across the <code>title</code> and <code>author</code> columns of the <code>Book</code> table, fetching up to 10 results. If no query parameter is provided, it defaults to fetching the first 20 books from the database. The results are passed to a new <code>search_results.html</code> template for rendering.</p>
<h3 id="heading-modifying-indexhtml-to-add-htmx">Modifying <code>index.html</code> to add HTMX</h3>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Book Search<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css"</span> /&gt;</span>
  <span class="hljs-comment">&lt;!-- Include HTMX library --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/htmx.org/dist/htmx.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"section"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"columns"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"column is-one-third is-offset-one-third"</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- HTMX-enabled search input --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">class</span>=<span class="hljs-string">"input"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search"</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"query"</span>
            <span class="hljs-attr">hx-get</span>=<span class="hljs-string">"/search"</span>
            <span class="hljs-attr">hx-trigger</span>=<span class="hljs-string">"keyup changed delay:500ms"</span>
            <span class="hljs-attr">hx-target</span>=<span class="hljs-string">"#results"</span>
          /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table is-fullwidth"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>ID<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Book Title<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Book Author<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"results"</span>&gt;</span>
        {% for book in books %}
          <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ book.id }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ book.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ book.author }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
        {% endfor %}
      <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The <code>&lt;script&gt;</code> tag imports the HTMX library from a CDN, enabling client-side interactions without requiring complex JavaScript. In addition to that, we enhance the <code>&lt;input&gt;</code> element with HTMX attributes:</p>
<ul>
<li><p><code>hx-get="/search"</code>: Specifies the endpoint (<code>/search</code>) to send GET requests when the user types in the input field.</p>
</li>
<li><p><code>hx-trigger="keyup changed delay:500ms"</code>: Triggers the search action after a 500ms delay when the user types (<code>keyup</code>) or changes the input (<code>changed</code>).</p>
</li>
<li><p><code>hx-target="#results"</code>: Updates the content of the element with <code>id="results"</code> with the response from the <code>/search</code> endpoint.</p>
</li>
</ul>
<h3 id="heading-creating-searchresultshtml-template">Creating <code>search_results.html</code> Template</h3>
<p>Next, we will create a new template <code>search_results.html</code> to display search results:</p>
<pre><code class="lang-xml">{% for result in results %}
<span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ result.id }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ result.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ result.author }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
{% endfor %}
</code></pre>
<p>This template iterates over <code>results</code>, which are passed from the <code>/search</code> route. For each book in <code>results</code>, it generates a table row (<code>&lt;tr&gt;</code>) displaying the book's ID, title, and author.</p>
<h2 id="heading-demo">Demo</h2>
<p>Finally, we have implemented instant search with HTMX in our Flask application. Here's what our final application should look like:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/llCmZXaopX0">https://youtu.be/llCmZXaopX0</a></div>
<p> </p>
<p>Did you notice the delay in the search results? It is called debouncing. It is a programming and web development technique to limit the rate at which a function or event handler is executed. It ensures that a function is only executed after a certain amount of time has passed since the last invocation of the function. In our case, we had set the delay of 500 ms before it hit the <code>/search</code> API. It ensures we do not hit the API for every character the user types.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, we learned how to implement instant search using Flask and HTMX, focusing on enhancing user interaction and performance. By integrating HTMX for AJAX interactions, we enabled dynamic updates to search results without refreshing the entire page. This approach improves user experience by providing real-time feedback and optimizes server load by debouncing search queries.</p>
<p>By mastering these techniques, you're equipped to build responsive web applications that deliver seamless search experiences, combining the flexibility of Flask with the interactivity of HTMX to meet diverse user needs efficiently and effectively.</p>
<p>You can find the code for this tutorial in this repository:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/ashutoshkrris/instant-search-with-flask-htmx">https://github.com/ashutoshkrris/instant-search-with-flask-htmx</a></div>
]]></content:encoded></item><item><title><![CDATA[How to Set Up Magic Link Authentication with React, Flask, and Authsignal]]></title><description><![CDATA[Authentication is the process of verifying the identity of a user or system. It ensures that only authorized individuals or systems can access certain resources or perform specific actions.
Magic Link Authentication offers a simple yet secure way for...]]></description><link>https://blog.ashutoshkrris.in/how-to-set-up-magic-link-authentication-with-react-flask-and-authsignal</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-set-up-magic-link-authentication-with-react-flask-and-authsignal</guid><category><![CDATA[Python]]></category><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[authentication]]></category><category><![CDATA[authsignal]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sat, 13 Jan 2024 07:24:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705130246382/1a51cb94-4991-476d-937c-ce44c4e2d37c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Authentication is the process of verifying the identity of a user or system. It ensures that only authorized individuals or systems can access certain resources or perform specific actions.</p>
<p>Magic Link Authentication offers a simple yet secure way for users to log in without passwords. This tutorial will walk you through the implementation of Magic Link Authentication using React for the front end, Flask for the back end, and the authentication service provided by <a target="_blank" href="https://www.authsignal.com/">Authsignal</a>.</p>
<h2 id="heading-understanding-magic-link-authentication"><strong>Understanding Magic Link Authentication</strong></h2>
<p>Magic link authentication is a convenient and secure authentication method that simplifies users' login process. Instead of entering a username and password, users receive a unique link via email. This link, known as a magic link, grants them access to their account without traditional credentials.</p>
<p>One key difference between magic link authentication and authentication with email verification is the user experience. With magic link authentication, users can authenticate with just a single click. They don't need to remember or enter a password, which can be especially beneficial for users who struggle with password management or find it inconvenient to type in their credentials repeatedly.</p>
<p>While email verification adds an extra layer of security, it may require the user to remember additional credentials or go through multiple steps before accessing their account. If you're interested in learning more about email verification, you can check out my article <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-set-up-email-verification-in-a-flask-app">here</a> to dive deeper into the topic.</p>
<h2 id="heading-how-to-configure-authsignal"><strong>How to Configure Authsignal</strong></h2>
<p><a target="_blank" href="https://www.authsignal.com/">Authsignal</a> is a service that makes implementing modern authentication methods (like Magic Links and Passkeys) easier. It provides simple tools to integrate secure login methods into your web apps without hassle.</p>
<p>Before proceeding with the tutorial, you need to create an Authsignal account. To do that, you can follow these steps:</p>
<p>First, go to <a target="_blank" href="https://www.freecodecamp.org/news">authsignal.com</a> and click on "Create Free Account".</p>
<p>In the next step, create your first tenant. Choose any name for your tenant and select the data storage region.</p>
<p><img src="https://lh7-us.googleusercontent.com/PoQ1Jl8b1fNXmzruv750erSeyi4jxnVlI_QAvoHDH6-O6GVHmDQ07yd2U7WxHrYTUMCyKowll7W-Bs0dBuet9KqiF-mZuV_w8IbFO5tpYziI5M5kaO1ipWEaJPJ7dkPWTNtXyib-BE-8S5VcVtanNNc" alt="Creating Tenant on Authsignal" /></p>
<p>Next, you need to configure the authenticators you want to use for your application. For example, I have enabled Email Magic Link and Authenticator App (TOTP).</p>
<p><img src="https://lh7-us.googleusercontent.com/AagTYGVbXToDeHqe4S-lFUx2qgIerUbzlUnGTv3sxZ2EyPBzfDeXNcvT-_oeQksckyhGFHX2YY6g8heKHdIz18qf2N_ejed9fJDFA_pSMzfKX3d5Tid4eDnrn7PUbEX_zVh10urhFa49Ek-eSYZJdAA" alt="Configuring Authenticators" /></p>
<p>Once you have configured the authenticator, navigate to the API Keys option. Here, you will find your Secret Key, which will be necessary for implementing the authentication.</p>
<p><img src="https://lh7-us.googleusercontent.com/UJgdqGLl6IRK8sr3NOsf1BXVp7EJpSFMkxTzdRw0QNhz7DqL5fyGMn7KBotMvrp3ivZnYtw8M-fdVX-aJgNrdszRyAziVCxIAXAxb-g8r42F9ZgQFlpm9D1FYicnhuS4DcS5V7hZ430FM5ruEUioiSw" alt="Finding your secret key" /></p>
<h2 id="heading-application-flow"><strong>Application Flow</strong></h2>
<p>Let's understand the flow of the application:</p>
<h3 id="heading-initial-visit"><strong>Initial Visit</strong></h3>
<ul>
<li>The user visits the application's user interface. On the user interface, they see a login input box and a signup option. Since the user is new, they opt to sign up.</li>
</ul>
<h3 id="heading-signup-flow"><strong>Signup Flow</strong></h3>
<ul>
<li><p>Upon clicking the signup link, the user is directed to a page to enter their chosen username.</p>
</li>
<li><p>After entering the username and clicking the signup button, the front end triggers a POST API call to /api/signup, sending the username in the request body.</p>
</li>
<li><p>The backend receives the request and communicates with the Authsignal server for user authentication.</p>
</li>
<li><p>Authsignal prompts the user to set up Magic Link authentication by entering their email address.</p>
</li>
<li><p>Authsignal sends a magic link to the provided email address.</p>
</li>
<li><p>After clicking the magic link, the user is authenticated and redirected to the home page, where they receive a welcome message displaying their email address. The page also includes a logout button.</p>
</li>
</ul>
<h3 id="heading-login-flow"><strong>Login Flow</strong></h3>
<ul>
<li><p>The user logs out and returns to the login page.</p>
</li>
<li><p>Here, the user enters their registered username and clicks the Login button.</p>
</li>
<li><p>Upon clicking Login, the front end triggers a POST API call to /api/login, passing the username in the request body.</p>
</li>
<li><p>The backend again communicates with Authsignal for user authentication, prompting the setup of Magic Link authentication.</p>
</li>
<li><p>The user is directed to a page to enter their email address.</p>
</li>
<li><p>Authsignal sends a magic link to the provided email address.</p>
</li>
<li><p>After clicking the magic link, the user is authenticated and redirected to the home page, greeted with a welcome message displaying their email address.</p>
</li>
</ul>
<p>This flow ensures users can sign up using a chosen username, and set up Magic Link authentication via email for both signup and login. Here is a video tutorial to visually aid you in understanding the flow:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/kr8frW5Wwcg">https://youtu.be/kr8frW5Wwcg</a></div>
<p> </p>
<h2 id="heading-how-to-set-up-your-backend-server"><strong>How to Set Up Your Backend Server</strong></h2>
<p>In this section, I will guide you through how to set up your Flask server for implementing Magic Link Authentication. Before we begin, it's recommended to set up a virtual environment to isolate your project's dependencies. Here's how you can do it:</p>
<ol>
<li><p>Open your terminal or command prompt.</p>
</li>
<li><p>Navigate to your project's directory.</p>
</li>
<li><p>Run the following command to create a new virtual environment:</p>
</li>
</ol>
<pre><code class="lang-bash">python -m venv myenv
</code></pre>
<p>Note: Replace <code>myenv</code> with the desired name for your virtual environment.</p>
<p>4.  Activate the virtual environment using the appropriate command for your operating system:</p>
<ul>
<li>For Windows:</li>
</ul>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> myenv/Scripts/activate
</code></pre>
<ul>
<li>For macOS/Linux:</li>
</ul>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> myenv/bin/activate
</code></pre>
<p>Now that you have your virtual environment set up, let's install the necessary dependencies.</p>
<p>To begin, make sure you have Flask installed, which is a micro web framework for Python. You can install it using the following one-liner:</p>
<pre><code class="lang-bash">pip install Flask
</code></pre>
<p>Next, we need <code>python-decouple</code>, a library that helps manage configuration settings in separate files. Install it with the following command:</p>
<pre><code class="lang-bash">pip install python-decouple
</code></pre>
<p>The <code>flask-cors</code> library is a Flask extension that allows for Cross-Origin Resource Sharing (CORS) support in your Flask application.</p>
<pre><code class="lang-bash">pip install flask-cors
</code></pre>
<p>Finally, we need to install the Python SDK for Authsignal. You can install it with the following command:</p>
<pre><code class="lang-bash">pip install authsignal
</code></pre>
<p>Now that we have all the necessary dependencies installed, let's create a sample Flask server to get started with Magic Link Authentication. Here's a basic setup to help you get started:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_cors <span class="hljs-keyword">import</span> CORS

app = Flask(__name__)
CORS(app, supports_credentials=<span class="hljs-literal">True</span>)

<span class="hljs-meta">@app.route("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, world!"</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>In the next steps, we will integrate AuthSignal and implement the Magic Link Authentication functionality into this server.</p>
<h2 id="heading-how-to-set-up-environment-variables"><strong>How to Set Up Environment Variables</strong></h2>
<p>To successfully configure and integrate AuthSignal into your Flask server, you need to set up the following environment variables:</p>
<ul>
<li><p><code>AUTHSIGNAL_BASE_URL</code>: This variable contains the base URL of the Authsignal server. It allows your server to communicate with Authsignal's authentication service.</p>
</li>
<li><p><code>AUTHSIGNAL_SECRET_KEY</code>: This variable contains the secret key associated with your Authsignal project. It is used for secure communication between your server and AuthSignal.</p>
</li>
<li><p><code>SECRET_KEY</code>: This variable is a random key used to encrypt the cookies and send them to the browser.</p>
</li>
</ul>
<p>Setting environment variables instead of hardcoding in the code provides improved security by keeping sensitive information, such as API keys and secret keys, separate from the codebase. This reduces the risk of accidental exposure or unauthorized access to these credentials.</p>
<p>To set up these environment variables, you can follow these steps:</p>
<ol>
<li><p>Open a terminal or command prompt.</p>
</li>
<li><p>Navigate to the directory where your Flask server is located.</p>
</li>
<li><p>Create a <code>.env</code> file and export the environment variables using the following commands:</p>
</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> AUTHSIGNAL_BASE_URL=&lt;base_url&gt;
<span class="hljs-built_in">export</span> AUTHSIGNAL_SECRET_KEY=&lt;secret_key&gt;
<span class="hljs-built_in">export</span> SECRET_KEY=&lt;random-secret-key&gt;
</code></pre>
<p>Make sure to replace <code>&lt;base_url&gt;</code>, <code>&lt;secret_key&gt;</code>, and <code>&lt;random-secret-key&gt;</code> with the appropriate values for your Authsignal project. You can find the values for these environment variables in the API Keys section of the Authsignal dashboard as explained earlier.</p>
<blockquote>
<p>Note: The method for setting environment variables can vary depending on your operating system. The above commands are applicable for Unix-based systems. For Windows, you can use the <code>set</code> command instead of <code>export</code>.</p>
</blockquote>
<p>To export the variables added in the .env file, you can use the following command in the terminal:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> .env
</code></pre>
<p>By properly setting these environment variables, your Flask server can securely communicate with Authsignal and implement the Magic Link Authentication functionality.</p>
<h2 id="heading-how-to-initialize-the-authsignal-client"><strong>How to Initialize the Authsignal Client</strong></h2>
<p>To integrate Authsignal into your Flask server and implement Magic Link Authentication, you need to initialize the Authsignal client. Here's an example of how you can do this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_cors <span class="hljs-keyword">import</span> CORS
<span class="hljs-keyword">import</span> authsignal.client
<span class="hljs-keyword">from</span> decouple <span class="hljs-keyword">import</span> config

app = Flask(__name__)
CORS(app)

AUTHSIGNAL_BASE_URL = config(<span class="hljs-string">"AUTHSIGNAL_BASE_URL"</span>)
AUTHSIGNAL_SECRET_KEY = config(<span class="hljs-string">"AUTHSIGNAL_SECRET_KEY"</span>)
SECRET_KEY = config(<span class="hljs-string">"SECRET_KEY"</span>)

authsignal_client = authsignal.Client(
    api_key=AUTHSIGNAL_SECRET_KEY,
    api_url=AUTHSIGNAL_BASE_URL
)
</code></pre>
<p>In this code snippet, we first import the <code>authsignal.client</code>, the Python SDK for Authsignal. We also import config from python-decouple to retrieve the environment variables.</p>
<p>We retrieve the environment variables <code>AUTHSIGNAL_BASE_URL</code>, <code>AUTHSIGNAL_SECRET_KEY</code> and <code>SECRET_KEY</code> using config from python-decouple.</p>
<p>Finally, we initialize the <code>authsignal.Client</code> by passing in the API key <code>AUTHSIGNAL_SECRET_KEY</code> and the base URL of the Authsignal server <code>AUTHSIGNAL_BASE_URL</code>.</p>
<p>By initializing the Authsignal client, we are ready to implement the Magic Link Authentication functionality in our Flask server.</p>
<h2 id="heading-authsignal-actions"><strong>Authsignal Actions</strong></h2>
<p>Authsignal allows you to create actions to track and manage user interactions in your application. Actions are events that can be triggered by users, such as signing up or logging in. By creating custom actions, you can have more control over the authentication process and implement specific authentication methods like Magic Link Authentication.</p>
<p>To create an action on your Authsignal dashboard, follow these steps:</p>
<ol>
<li><p>Click on "<strong>Actions</strong>" in your Authsignal dashboard.</p>
</li>
<li><p>Click on "<strong>Configure a new action</strong>" to create a new action.</p>
</li>
<li><p>Enter a name for the action that describes its purpose or the user interaction it represents.</p>
</li>
<li><p>Next, you can configure the rule for the action. In our case, since we want to implement Magic Link Authentication, we will add a rule to challenge users with Email Magic Link. This will send a magic link to the user's email for authentication.</p>
</li>
<li><p>Save the action to apply the rule and make it active.</p>
</li>
</ol>
<p>Here is a video demonstrating the process of creating an Authsignal action and configuring it for Magic Link Authentication:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/action.gif" alt="Creating action on Authsignal" /></p>
<p>You can create two actions – "<strong>signUp</strong>" and "<strong>signIn</strong>". In the next steps, we will make use of these actions.</p>
<h2 id="heading-how-to-create-the-required-routes"><strong>How to Create the Required Routes</strong></h2>
<p>Finally, to implement the Magic Link Authentication, we need to create three routes: <code>/api/signup</code>, <code>/api/login</code>, <code>/api/callback</code>, and <code>/api/user</code>.</p>
<h3 id="heading-apisignup-route"><code>/api/signup</code> Route</h3>
<p>The <code>/api/signup</code> route is responsible for allowing the users to register in our application. Here's how we implement it:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route('/api/signup', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">signup</span>():</span>
    username = request.json.get(<span class="hljs-string">'username'</span>)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> username:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Missing username parameter'</span>}), <span class="hljs-number">400</span>

    response = authsignal_client.track(
        user_id=username,
        action=<span class="hljs-string">"signUp"</span>,
        payload={
            <span class="hljs-string">"user_id"</span>: username,
            <span class="hljs-string">"redirectUrl"</span>: <span class="hljs-string">"http://localhost:5000/api/callback"</span>
        }
    )
    <span class="hljs-keyword">return</span> jsonify(response), <span class="hljs-number">200</span>
</code></pre>
<p>In this implementation, the route expects a JSON payload containing the <code>username</code> parameter. It then uses the <code>authsignal_client</code> to track the user's <strong>signUp</strong> action and generate a Magic Link. The <code>track</code> method lets you record actions performed by users and initiate challenges. The <code>redirectUrl</code> specifies the URL where the user will be redirected after they have been authenticated. We will create this API next.</p>
<h3 id="heading-apicallback-route"><code>/api/callback</code> Route</h3>
<p>The <code>/api/callback</code> route handles the callback URL where the user is redirected after verifying themselves. Here's the implementation for this route:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route('/api/callback', methods=['GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">callback</span>():</span>
    token = request.args.get(<span class="hljs-string">'token'</span>)
    challenge_response = authsignal_client.validate_challenge(token)

    <span class="hljs-keyword">if</span> challenge_response[<span class="hljs-string">"state"</span>] == <span class="hljs-string">'CHALLENGE_SUCCEEDED'</span>:
        encoded_token = jwt.encode(
            payload={<span class="hljs-string">"username"</span>: challenge_response[<span class="hljs-string">"user_id"</span>]},
            key=SECRET_KEY,
            algorithm=<span class="hljs-string">"HS256"</span>
        )
        response = redirect(<span class="hljs-string">'http://localhost:3000/'</span>)
        response.set_cookie(
            key=<span class="hljs-string">'auth-session'</span>,
            value=encoded_token,
            secure=<span class="hljs-literal">False</span>,
            path=<span class="hljs-string">'/'</span>
        )
        <span class="hljs-keyword">return</span> response

    <span class="hljs-keyword">return</span> redirect(<span class="hljs-string">"/"</span>)
</code></pre>
<p>When the users are redirected, Authsignal adds the JWT token in the URL as a token query parameter.</p>
<p>In this implementation, the route retrieves the token parameter from the query string. It then uses the <code>authsignal_client</code> to validate the challenge and check if the authentication was successful.</p>
<p>If the authentication succeeds, we encode a JSON Web Token (JWT). The token payload includes the <code>username</code> obtained from the challenge response. It uses the <code>SECRET_KEY</code> and the <em>HS256 algorithm</em> for encryption.</p>
<p>Next, the user is redirected to the home page (<a target="_blank" href="https://www.freecodecamp.org/news">http://localhost:3000/</a>), and a <code>auth-session</code> cookie is set with the encoded token for further user identification.</p>
<p>Note that the token returned from Authsignal in the redirect is not intended to be used as a session token. It just contains information about the challenge so that we can determine if the challenge was successful.</p>
<h3 id="heading-apilogin-route"><code>/api/login</code> Route</h3>
<p>The <code>/api/login</code> route is responsible for allowing the users to log into the application. Here’s the implementation for the route:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route('/api/login', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">login</span>():</span>
    username = request.json.get(<span class="hljs-string">'username'</span>)
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> username:
        <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">'error'</span>: <span class="hljs-string">'Missing username parameter'</span>}), <span class="hljs-number">400</span>

    response = authsignal_client.track(
        user_id=username,
        action=<span class="hljs-string">"signIn"</span>,
        payload={
            <span class="hljs-string">"user_id"</span>: username,
            <span class="hljs-string">"redirectUrl"</span>: <span class="hljs-string">"http://localhost:5000/api/callback"</span>
        }
    )
    <span class="hljs-keyword">return</span> jsonify(response), <span class="hljs-number">200</span>
</code></pre>
<p>The route is configured to handle POST requests on the <code>/api/login</code> endpoint. Upon receiving a POST request, the route first extracts the provided <code>username</code> from the JSON payload sent with the request. It ensures that the username is present. If not, it promptly returns a 400 error response indicating a missing username parameter.</p>
<p>Similar to the signup flow, it then uses the <code>authsignal_client</code> to track the user's <strong>signIn</strong> action and generate a Magic Link. The redirectUrl specifies the URL where the user will be redirected after they have been authenticated.</p>
<h3 id="heading-apiuser-route"><code>/api/user</code> Route</h3>
<p>The <code>/api/user</code> route is responsible for retrieving user information. Here's the implementation for this route:</p>
<pre><code class="lang-python"><span class="hljs-meta">@app.route("/api/user", methods=['GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user</span>():</span>
    token = request.cookies.get(<span class="hljs-string">'auth-session'</span>)
    decoded_token = jwt.decode(token, SECRET_KEY, algorithms=[<span class="hljs-string">"HS256"</span>])
    username = decoded_token.get(<span class="hljs-string">'username'</span>)
    response = authsignal_client.get_user(user_id=username)
    <span class="hljs-keyword">return</span> jsonify({<span class="hljs-string">"username"</span>: username, <span class="hljs-string">"email"</span>: response[<span class="hljs-string">"email"</span>]}), <span class="hljs-number">200</span>
</code></pre>
<p>In this implementation, the GET endpoint starts by extracting the auth-session cookie from the incoming request. Then it decodes the JWT using the jwt.decode method, utilizing the <code>SECRET_KEY</code> as the secret key for decoding.</p>
<p>The decoded token provides the username of the user. It then uses the <code>authsignal_client</code> to retrieve user information based on the provided <code>userId</code>. It then returns a JSON response with the username and email information.</p>
<p>By implementing these routes, we will be able to handle the basic authentication process and retrieve user information in our Flask server.</p>
<h2 id="heading-how-to-set-up-a-new-frontend-react-project"><strong>How to Set Up a New Frontend React Project</strong></h2>
<p>Let's set up our front-end project in this section. This will also include setting up routing in the application.</p>
<p>Start by initializing a new React project using <code>create-react-app</code> or any preferred method (<a target="_blank" href="https://www.freecodecamp.org/news/complete-vite-course-for-beginners/">like Vite</a>, for example, which is a more modern way to set up a React app). This command sets up the basic structure for your React application.</p>
<pre><code class="lang-bash">npx create-react-app magic-link-auth
<span class="hljs-built_in">cd</span> magic-link-auth
</code></pre>
<p>Once the project is created and you're inside the project directory, install the required dependencies. Here, we need <code>react-router-dom</code> for handling routing and <code>bootstrap</code> for easy styling.</p>
<pre><code class="lang-bash">npm install react-router-dom bootstrap
</code></pre>
<h3 id="heading-import-bootstrap-css"><strong>Import Bootstrap CSS</strong></h3>
<p>Bootstrap provides pre-styled components and utilities for easier and faster styling of your application.</p>
<p>In the <code>index.js</code> file, import Bootstrap:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">'./reportWebVitals'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"bootstrap/dist/css/bootstrap.min.css"</span>; <span class="hljs-comment">// Import Bootstrap CSS</span>

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));
root.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);

<span class="hljs-comment">// If you want to start measuring performance in your app, pass a function</span>
<span class="hljs-comment">// to log results (for example: reportWebVitals(console.log))</span>
<span class="hljs-comment">// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals</span>
reportWebVitals();
</code></pre>
<p>Additionally, we will write some custom CSS. Replace the code in the <code>index.css</code> file with the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span>,
<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">font-family</span>: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

* {
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-tag">main</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">5rem</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
}

<span class="hljs-selector-tag">code</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#fafafa</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.75rem</span>;
  <span class="hljs-attribute">font-family</span>: Menlo, Monaco, Lucida Console, Courier New, monospace;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">"button"</span>]</span> {
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">background</span>: cornflowerblue;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">12px</span> <span class="hljs-number">24px</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<p>Similarly, replace the code in the <code>App.css</code> with the following code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.mainContainer</span> {
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
}

<span class="hljs-selector-class">.titleContainer</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">48px</span>;
  <span class="hljs-attribute">font-weight</span>: bolder;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
}

<span class="hljs-selector-class">.resultContainer</span>,
<span class="hljs-selector-class">.historyItem</span> {
  <span class="hljs-attribute">flex-direction</span>: row;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">400px</span>;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: space-between;
}

<span class="hljs-selector-class">.historyContainer</span> {
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">flex-grow</span>: <span class="hljs-number">5</span>;
  <span class="hljs-attribute">justify-content</span>: flex-start;
}

<span class="hljs-selector-class">.buttonContainer</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">260px</span>;
}

<span class="hljs-selector-class">.inputContainer</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">align-items</span>: flex-start;
  <span class="hljs-attribute">justify-content</span>: center;
}

<span class="hljs-selector-class">.inputContainer</span>&gt;<span class="hljs-selector-class">.errorLabel</span> {
  <span class="hljs-attribute">color</span>: red;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-class">.inputBox</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">48px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">400px</span>;
  <span class="hljs-attribute">font-size</span>: medium;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid grey;
  <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">8px</span>;
}

<span class="hljs-selector-class">.inputButton</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">48px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">400px</span>;
}
</code></pre>
<h3 id="heading-set-up-routing"><strong>Set Up Routing</strong></h3>
<p>Routing in React applications helps navigate between different views or pages. <code>react-router-dom</code> simplifies this process.</p>
<p>In your <code>App.js</code> file, configure the routing:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { BrowserRouter, Routes, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> Dashboard <span class="hljs-keyword">from</span> <span class="hljs-string">"./pages/Dashboard"</span>;
<span class="hljs-keyword">import</span> Register <span class="hljs-keyword">from</span> <span class="hljs-string">"./pages/Register"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./pages/Login"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/login"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Login</span> /&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/signup"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Register</span> /&gt;</span>} /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>It defines an App component that encapsulates the entire application structure within a <code>&lt;BrowserRouter&gt;</code> component. Inside <code>&lt;Routes&gt;</code>, we define three &lt;Route&gt; components: one for the root path <code>/</code> rendering the <code>Dashboard</code> component, and two for the <code>/login</code> and <code>/signup</code>  paths, rendering the <code>Login</code> and <code>Register</code> components respectively.</p>
<p>This setup enables navigation between different views based on URL paths, allowing users to access specific components when they visit corresponding routes within the application.</p>
<p>In the upcoming sections, we will set up the above-mentioned three components.</p>
<h2 id="heading-how-to-set-up-the-components"><strong>How to Set Up the Components</strong></h2>
<p>In the previous section, we imported two components from the <code>src/pages</code> folder. Let's create a <code>pages</code> folder inside the <code>src</code> folder, and then we can start creating the components.</p>
<h3 id="heading-register-component"><strong>Register Component</strong></h3>
<p>Let’s create a <code>Register.jsx</code> file inside the pages folder. The <strong>Register</strong> component allows users to register within our application.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useNavigate, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">const</span> Register = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [username, setUsername] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [usernameError, setUsernameError] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> navigate = useNavigate();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> isAuthenticated = checkCookies();
    <span class="hljs-keyword">if</span> (isAuthenticated) {
      navigate(<span class="hljs-string">"/"</span>);
    }
  }, [navigate]);

  <span class="hljs-keyword">const</span> checkCookies = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> authSessionCookie = <span class="hljs-built_in">document</span>.cookie.match(<span class="hljs-string">"auth-session=([^;]+)"</span>);

    <span class="hljs-keyword">return</span> !!authSessionCookie;
  };

  <span class="hljs-keyword">const</span> onButtonClick = <span class="hljs-function">() =&gt;</span> {
    setUsernameError(<span class="hljs-string">""</span>);

    <span class="hljs-keyword">if</span> (<span class="hljs-string">""</span> === username) {
      setUsernameError(<span class="hljs-string">"Username is mandatory!"</span>);
      <span class="hljs-keyword">return</span>;
    }

    signup();
  };

  <span class="hljs-keyword">const</span> signup = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:5000/api/login"</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        username,
      }),
      <span class="hljs-attr">credentials</span>: <span class="hljs-string">"include"</span>,
    });

    <span class="hljs-keyword">const</span> { url } = <span class="hljs-keyword">await</span> response.json();

    <span class="hljs-comment">// Redirect to verification URL</span>
    <span class="hljs-built_in">window</span>.location.href = url;
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">mainContainer</span>"}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">titleContainer</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Sign Up<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">inputContainer</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{username}</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your username"</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setUsername(e.target.value)}
          className={"inputBox"}
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorLabel text-center"</span>&gt;</span>{usernameError}<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">inputContainer</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">inputButton</span>"}
          <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onButtonClick}</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">Sign</span> <span class="hljs-attr">Up</span>"}
        /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Existing User? <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span>&gt;</span>Login here<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Register;
</code></pre>
<p>The component initializes state variables using <code>useState</code> to manage the visibility of the <code>usernameError</code> and store the username input in <code>userName</code>. It also initializes the <code>navigate</code> function from <code>useNavigate</code> to handle navigation within the application.</p>
<p>We use the <code>useEffect</code> hook to check for authentication cookies when the component mounts. It calls the <code>checkCookies</code> function, which checks for the existence of cookies that we had set from the backend server. If <code>auth-session</code> cookie is found, the user is automatically redirected to the root URL using navigate("/").</p>
<p>Clicking the “Sign Up” button triggers the <code>onButtonClick</code> function. It first checks whether the user has entered the username. If not, it shows an error message using the <code>usernameError</code>. If the user has entered the username, it calls the <code>signup</code> function.</p>
<p>The <code>signup</code> performs an asynchronous POST request to the <code>/api/signup</code> endpoint with the provided username. Upon successful response, it redirects the user to the received verification URL by changing window.location.href.</p>
<p>The JSX returned by the component defines the UI layout that looks like the below:</p>
<p><img src="https://lh7-us.googleusercontent.com/gncsDRe9QVK20DWMkiWwdGOt_ZymbSVXTv-8UGvyKIpp5-TZ64-DwLGLbMtDM0B-wgXh8jNOCdkA0kia3-gJftMxFaH-za_4O0cqCSvK9GLMHSbO_nH_UfgGIf5QhHaOZg559_N0c4P9Oof4O5JmkPE" alt="Register UI Component" /></p>
<p>It includes an input field for the users to enter their username and a "Sign Up" button. Below the button, we have a link to the Login page for the existing users to log in.</p>
<h3 id="heading-login-component"><strong>Login Component</strong></h3>
<p>We have kept the login page similar to the signup page for simplicity. Hence, the Login component is pretty much the same as the Register component.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useNavigate, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">const</span> Login = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [username, setUsername] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [usernameError, setUsernameError] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> navigate = useNavigate();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> isAuthenticated = checkCookies();
    <span class="hljs-keyword">if</span> (isAuthenticated) {
      navigate(<span class="hljs-string">"/"</span>);
    }
  }, [navigate]);

  <span class="hljs-keyword">const</span> checkCookies = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> authSessionCookie = <span class="hljs-built_in">document</span>.cookie.match(<span class="hljs-string">"auth-session=([^;]+)"</span>);

    <span class="hljs-keyword">return</span> !!authSessionCookie;
  };

  <span class="hljs-keyword">const</span> onButtonClick = <span class="hljs-function">() =&gt;</span> {
    setUsernameError(<span class="hljs-string">""</span>);

    <span class="hljs-keyword">if</span> (<span class="hljs-string">""</span> === username) {
      setUsernameError(<span class="hljs-string">"Username is mandatory!"</span>);
      <span class="hljs-keyword">return</span>;
    }

    login();
  };

  <span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:5000/api/login"</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        username,
      }),
      <span class="hljs-attr">credentials</span>: <span class="hljs-string">"include"</span>,
    });

    <span class="hljs-keyword">const</span> { url } = <span class="hljs-keyword">await</span> response.json();

    <span class="hljs-comment">// Redirect to verification URL</span>
    <span class="hljs-built_in">window</span>.location.href = url;
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">mainContainer</span>"}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">titleContainer</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">inputContainer</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{username}</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter your username"</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(ev)</span> =&gt;</span> setUsername(ev.target.value)}
          className={"inputBox"}
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"errorLabel text-center"</span>&gt;</span>{usernameError}<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">inputContainer</span>"}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">inputButton</span>"}
          <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onButtonClick}</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">Log</span> <span class="hljs-attr">in</span>"}
        /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        New User? <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/signup"</span>&gt;</span>Sign up here<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Login;
</code></pre>
<p>The only significant difference other than the text and button in the UI here is that we will be making the API call to the <code>/api/login</code> route when the users hit the Login button.</p>
<p>The UI looks like below:</p>
<p><img src="https://lh7-us.googleusercontent.com/F4EDOhuMbTRtXt3UxhpLYdZPT8XtCuYWjEX3H95bEXEZatLDsuRxaut3KZ3ZtyHSWIQ1WkuA5WWUxZcXrCBHyCMfMG-LQTKjnQHXyY8Y2Ha93YstE0Kycd9ji9lj33wMc1D8Km7pFNu5EGyQh14D9m8" alt="Login UI Component" /></p>
<h3 id="heading-dashboard-component"><strong>Dashboard Component</strong></h3>
<p>The Dashboard component in our application serves as the interface for authenticated users, displaying a welcome message with the user’s email and enabling user logout functionality.</p>
<p>Let’s create a <code>Dashboard.jsx</code> file inside the <code>pages</code> folder.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">const</span> Dashboard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [userEmail, setUserEmail] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> checkCookies = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> authSessionCookie = <span class="hljs-built_in">document</span>.cookie.match(<span class="hljs-string">"auth-session=([^;]+)"</span>);

      <span class="hljs-keyword">if</span> (!authSessionCookie) {
        navigate(<span class="hljs-string">"/auth"</span>);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
      }

      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    };

    <span class="hljs-keyword">const</span> fetchData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> cookiesValid = <span class="hljs-keyword">await</span> checkCookies();
      <span class="hljs-keyword">if</span> (!cookiesValid) <span class="hljs-keyword">return</span>;

      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"http://localhost:5000/api/user"</span>, {
          <span class="hljs-attr">method</span>: <span class="hljs-string">"GET"</span>,
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
          },
          <span class="hljs-attr">credentials</span>: <span class="hljs-string">"include"</span>
        });

        <span class="hljs-keyword">if</span> (!response.ok) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to fetch user data"</span>);
        }

        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
        setUserEmail(data.email);
      } <span class="hljs-keyword">catch</span> (error) {
        navigate(<span class="hljs-string">"/auth"</span>);
      }
    };

    fetchData();
  }, [navigate]);

  <span class="hljs-keyword">const</span> handleLogout = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.cookie = <span class="hljs-string">`auth-session=; max-age=0`</span>;
    navigate(<span class="hljs-string">"/auth"</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"d-flex justify-content-center align-items-center vh-100"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"px-3 text-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome Home!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"lead"</span>&gt;</span>You're logged in as {userEmail}!<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"d-flex justify-content-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"btn btn-lg btn-dark fw-bold border-white bg-dark"</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleLogout}</span>
          &gt;</span>
            Log Out
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Dashboard;
</code></pre>
<p>Upon component mounting or when <code>navigate</code> changes (a dependency of <code>useEffect</code>), the effect runs. It begins by defining two asynchronous functions. The first, <code>checkCookies</code>, verifies the presence of <code>auth-session</code> cookies. If it is missing, it redirects the user to the authentication route.</p>
<p>The second function, <code>fetchData</code>, is responsible for fetching user data. It checks the validity of cookies using <code>checkCookies</code>. Upon verification, it sends a GET request to our back-end API endpoint. Upon successful response, it updates the <code>userEmail</code> state with the user's email fetched from the API data.</p>
<p>If any error occurs during this process, such as failing to fetch user data, it redirects the user back to the authentication route.</p>
<p>The JSX returned by the component renders a simple dashboard layout.</p>
<p><img src="https://lh7-us.googleusercontent.com/ca-epjkteyLzE_dVbbWN6bC5fMVogCJLRvR8Milfjl7UzoHRK7462_YJZhkJvhoTpBtD0sNFwpGbNaLTKNEuBg6wKSxv6j5-ApmjpOtPgx-UkeM8i39A0KwAuU3L2TeRc8R_3aXugnAMcH4iGrlBP0M" alt="Dashboard UI Component" /></p>
<p>The displayed content includes a welcoming message and the currently logged-in user's email. There's also a "Log Out" button which, upon clicking, initiates the logout process by triggering the <code>handleLogout</code> function. It removes the <code>auth-session</code> cookies by setting their <code>max-age</code> to 0, effectively expiring them. Afterward, it redirects the user to the authentication route.</p>
<h2 id="heading-how-to-run-the-application"><strong>How to Run the Application</strong></h2>
<p>You can find the code of the final application in this <a target="_blank" href="https://github.com/ashutoshkrris/authsignal-magic-link-demo">GitHub repository</a>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/ashutoshkrris/authsignal-magic-link-demo">https://github.com/ashutoshkrris/authsignal-magic-link-demo</a></div>
<p> </p>
<p>To run your backend application, run <code>python</code> <a target="_blank" href="https://www.freecodecamp.org/news"><code>app.py</code></a> from your back-end folder in your terminal. This will start your back-end server on port 5000. Next, run the frontend application using the <code>npm start</code> command. This will start your frontend application on the port 3000.</p>
<h2 id="heading-wrapping-up"><strong>Wrapping Up</strong></h2>
<p>In this tutorial, you learned how to use Authsignal to implement basic user authentication with email verification through magic links.</p>
<p>Authsignal makes handling users and keeping things safe easier, letting developers focus on improving apps. It also removes the overhead of remembering another password for the users of the application.</p>
<p>To learn more about Authsignal, <a target="_blank" href="https://docs.authsignal.com/">visit the Authsignal documentation</a>.</p>
<blockquote>
<p>Should you have any issues or questions related to the tutorial, then feel free to reach out to me on <a target="_blank" href="https://twitter.com/ashutoshkrris">Twitter</a>.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How to Implement Two-Factor Authentication with PyOTP and Google Authenticator in Your Flask App]]></title><description><![CDATA[Two-factor authentication, or 2FA, is like having an extra lock on the door to your online accounts. Instead of just using a password, 2FA adds another layer of security. It's a bit like needing both a key and a special code to open a vault.
Think of...]]></description><link>https://blog.ashutoshkrris.in/how-to-implement-two-factor-authentication-with-pyotp-and-google-authenticator-in-your-flask-app</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-implement-two-factor-authentication-with-pyotp-and-google-authenticator-in-your-flask-app</guid><category><![CDATA[Python]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[authentication]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Thu, 30 Nov 2023 02:25:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1701310653950/695ba990-3bbf-439b-8fd7-ba73fa8d3fb0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Two-factor authentication, or 2FA, is like having an extra lock on the door to your online accounts. Instead of just using a password, 2FA adds another layer of security. It's a bit like needing both a key and a special code to open a vault.</p>
<p>Think of it as a shield for your accounts. Passwords can sometimes be guessed or stolen, but with 2FA, even if someone gets your password, they'd still need that extra code or device to get in. It's an extra step that makes your accounts much harder for hackers to break into.</p>
<p>So, let's explore how to set up this extra layer of protection using PyOTP and Google Authenticator in your Flask app.</p>
<h2 id="heading-overview-of-pyotp-and-google-authenticator"><strong>Overview of PyOTP and Google Authenticator</strong></h2>
<p>PyOTP is a Python library that's incredibly handy for generating Time-based One-Time Passwords (TOTP) and HMAC-based One-Time Passwords (HOTP). Its primary role revolves around creating these unique, time-sensitive codes that add an extra layer of security to user accounts.</p>
<p>By integrating PyOTP into your Flask application, you can easily implement Two-Factor Authentication (2FA) by generating and verifying these OTPs.</p>
<blockquote>
<p>If you're new to PyOTP or would like a refresher on its functionalities, I recommend reviewing my previous <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-generate-otps-using-pyotp-in-python">guide on PyOTP</a>. This understanding will be beneficial as we get into the integration of PyOTP within your Flask application for Two-Factor Authentication (2FA).</p>
</blockquote>
<p>Google Authenticator, on the other hand, stands out as one of the most widely used OTP generator apps available. It functions as a secure platform for generating time-based OTPs, compatible with various services and applications supporting 2FA. Users can easily set up Google Authenticator on their devices to generate these time-sensitive codes, adding an extra level of security to their accounts.</p>
<h2 id="heading-two-factor-authentication-workflow-in-our-application"><strong>Two-Factor Authentication Workflow in Our Application</strong></h2>
<p>Here's a breakdown of the flow of two-factor authentication in our application:</p>
<ol>
<li><p><strong>Registration with 2FA Setup</strong>: When users sign up on our website, they're prompted to set up an extra layer of security—2FA. This involves scanning a QR code using an authenticator app, such as Google Authenticator, to link their account securely.</p>
</li>
<li><p><strong>Login Initiation</strong>: When users return to log in, they start by entering their usual email/username and password combo to access their account.</p>
</li>
<li><p><strong>Extra Security Check</strong>: Before granting access, our website throws in an additional hurdle: users need to provide an OTP (One-Time Password) displayed on their authenticator app. This ensures they're not just entering the password but also confirming their identity with a unique, time-sensitive code.</p>
</li>
<li><p><strong>Validation and Authorization</strong>: The user inputs the received OTP into our platform. The system then double-checks this OTP against the expected code, validating the information. If the OTP matches, it's like handing over the secret handshake, granting the user access to their account.</p>
</li>
</ol>
<p>This seamless back-and-forth between passwords, authenticator apps, and unique codes ensures that only the rightful account owner can access the precious content behind the digital doors of your website.</p>
<p>If you also enjoy visual learning, here's a fancy video showing how the app does its thing.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/qzLcbq5-UNA">https://youtu.be/qzLcbq5-UNA</a></div>
<p> </p>
<p>Now, let's get to some coding!</p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before you get started with the tutorial, make sure you have the following requirements satisfied:</p>
<ul>
<li><p>Working knowledge of Python</p>
</li>
<li><p>Python 3.8+ installed on your system</p>
</li>
<li><p>Basic knowledge of <a target="_blank" href="https://ashutoshkrris.hashnode.dev/getting-started-with-flask">Flask</a> and <a target="_blank" href="https://ashutoshkrris.hashnode.dev/how-to-use-blueprints-to-organize-your-flask-apps">Flask Blueprints</a></p>
</li>
<li><p>Knowledge of <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-set-up-basic-user-authentication-in-a-flask-app">basic authentication in Flask</a> (optional)</p>
</li>
</ul>
<h2 id="heading-get-your-tools-ready"><strong>Get Your Tools Ready</strong></h2>
<p>You'll need a few external libraries for this project. Let's learn more about them and install them one by one.</p>
<p>But before we install them, let's create a virtual environment and activate it.</p>
<p>First, start with creating the project directory and navigating to it like this:</p>
<pre><code class="lang-bash">mkdir flask-two-factor-auth
<span class="hljs-built_in">cd</span> flask-two-factor-auth
</code></pre>
<p>We are going to create a virtual environment using <code>venv</code>. Python now ships with a pre-installed <code>venv</code> library. So, to create a virtual environment, you can use the below command:</p>
<pre><code class="lang-bash">python -m venv env
</code></pre>
<p>The above command will create a virtual environment named env. Now, we need to activate the environment using this command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> env/Scripts/activate
</code></pre>
<p>To verify if the environment has been activated or not, you can see <code>(env)</code> in your terminal. Now, we can install the libraries.</p>
<ul>
<li><p><a target="_blank" href="https://flask.palletsprojects.com/en/2.2.x/">Flask</a> is a simple, easy-to-use microframework for Python that helps you build scalable and secure web applications.</p>
</li>
<li><p><a target="_blank" href="https://flask-login.readthedocs.io/en/latest/">Flask-Login</a> provides user session management for Flask. It handles the common tasks of logging in, logging out, and remembering your users’ sessions over extended periods.</p>
</li>
<li><p><a target="_blank" href="https://flask-bcrypt.readthedocs.io/en/1.0.1/">Flask-Bcrypt</a> is a Flask extension that provides bcrypt hashing utilities for your application.</p>
</li>
<li><p><a target="_blank" href="https://flask-wtf.readthedocs.io/en/1.0.x/">Flask-WTF</a> is a simple integration of Flask and WTForms that helps you create forms in Flask.</p>
</li>
<li><p><a target="_blank" href="https://flask-migrate.readthedocs.io/en/latest/">Flask-Migrate</a> is an extension that handles SQLAlchemy database migrations for Flask applications using Alembic. The database operations are made available through the Flask command-line interface.</p>
</li>
<li><p><a target="_blank" href="https://flask-sqlalchemy.palletsprojects.com/en/2.x/">Flask-SQLAlchemy</a> is an extension for Flask that adds support for SQLAlchemy to your application. It helps you simplify things using SQLAlchemy with Flask by giving you useful defaults and extra helpers that make it easier to perform common tasks.</p>
</li>
<li><p><a target="_blank" href="https://blog.ashutoshkrris.in/how-to-generate-otps-using-pyotp-in-python">PyOTP</a> helps you generate OTPs using Time-based OTP (TOTP) and HMAC-based OTP (HOTP) algorithms effortlessly.</p>
</li>
<li><p><a target="_blank" href="https://pypi.org/project/qrcode/">QRCode</a> helps you generate QR Codes in Python</p>
</li>
<li><p><a target="_blank" href="https://pypi.org/project/python-decouple/">Python Decouple</a> helps you use environment variables in your Python project.</p>
</li>
</ul>
<p>To install the above-mentioned libraries all in one go, run the following command:</p>
<pre><code class="lang-bash">pip install Flask Flask-Login Flask-Bcrypt Flask-WTF FLask-Migrate Flask-SQLAlchemy pyotp qrcode python-decouple
</code></pre>
<h2 id="heading-how-to-set-up-the-project"><strong>How to Set Up the Project</strong></h2>
<p>Let’s start by creating a <code>src</code> directory:</p>
<pre><code class="lang-bash">mkdir src
</code></pre>
<p>The first file will be the <code>__init__.py</code> file for the project:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> decouple <span class="hljs-keyword">import</span> config
<span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_bcrypt <span class="hljs-keyword">import</span> Bcrypt
<span class="hljs-keyword">from</span> flask_migrate <span class="hljs-keyword">import</span> Migrate
<span class="hljs-keyword">from</span> flask_sqlalchemy <span class="hljs-keyword">import</span> SQLAlchemy

app = Flask(__name__)
app.config.from_object(config(<span class="hljs-string">"APP_SETTINGS"</span>))

bcrypt = Bcrypt(app)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

<span class="hljs-comment"># Registering blueprints</span>
<span class="hljs-keyword">from</span> src.accounts.views <span class="hljs-keyword">import</span> accounts_bp
<span class="hljs-keyword">from</span> src.core.views <span class="hljs-keyword">import</span> core_bp

app.register_blueprint(accounts_bp)
app.register_blueprint(core_bp)
</code></pre>
<p>In the above script, we created a Flask app called <code>app</code> . We use the <code>__name__</code> argument to indicate the app's module or package so that Flask knows where to find other files such as templates. We also set the configuration of the app using an environment variable called <code>APP_SETTINGS</code>. We'll export it later.</p>
<p>To use Flask-Bcrypt, Flask-SQLAlchemy, and Flask-Migrate in our application, we just need to create objects of the <code>Bcrypt</code>, <code>SQLAlchemy</code> and <code>Migrate</code> classes from the <code>flask_bcrypt</code>, <code>flask_sqlalchemy</code> and, <code>flask_migrate</code> libraries, respectively.</p>
<p>We've also registered blueprints called <code>accounts_bp</code> and <code>core_bp</code> in the application. We'll define them later in the tutorial.</p>
<p>In the root directory of the project (that is, outside the <code>src</code> directory), create a file called <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>config.py</code></a>. We'll store the configurations for the project in this file. Within the file, add the following content:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> decouple <span class="hljs-keyword">import</span> config

DATABASE_URI = config(<span class="hljs-string">"DATABASE_URL"</span>)
<span class="hljs-keyword">if</span> DATABASE_URI.startswith(<span class="hljs-string">"postgres://"</span>):
    DATABASE_URI = DATABASE_URI.replace(<span class="hljs-string">"postgres://"</span>, <span class="hljs-string">"postgresql://"</span>, <span class="hljs-number">1</span>)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>(<span class="hljs-params">object</span>):</span>
    DEBUG = <span class="hljs-literal">False</span>
    TESTING = <span class="hljs-literal">False</span>
    CSRF_ENABLED = <span class="hljs-literal">True</span>
    SECRET_KEY = config(<span class="hljs-string">"SECRET_KEY"</span>, default=<span class="hljs-string">"guess-me"</span>)
    SQLALCHEMY_DATABASE_URI = DATABASE_URI
    SQLALCHEMY_TRACK_MODIFICATIONS = <span class="hljs-literal">False</span>
    BCRYPT_LOG_ROUNDS = <span class="hljs-number">13</span>
    WTF_CSRF_ENABLED = <span class="hljs-literal">True</span>
    DEBUG_TB_ENABLED = <span class="hljs-literal">False</span>
    DEBUG_TB_INTERCEPT_REDIRECTS = <span class="hljs-literal">False</span>
    APP_NAME = config(<span class="hljs-string">"APP_NAME"</span>)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DevelopmentConfig</span>(<span class="hljs-params">Config</span>):</span>
    DEVELOPMENT = <span class="hljs-literal">True</span>
    DEBUG = <span class="hljs-literal">True</span>
    WTF_CSRF_ENABLED = <span class="hljs-literal">False</span>
    DEBUG_TB_ENABLED = <span class="hljs-literal">True</span>


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestingConfig</span>(<span class="hljs-params">Config</span>):</span>
    TESTING = <span class="hljs-literal">True</span>
    DEBUG = <span class="hljs-literal">True</span>
    SQLALCHEMY_DATABASE_URI = <span class="hljs-string">"sqlite:///testdb.sqlite"</span>
    BCRYPT_LOG_ROUNDS = <span class="hljs-number">1</span>
    WTF_CSRF_ENABLED = <span class="hljs-literal">False</span>


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductionConfig</span>(<span class="hljs-params">Config</span>):</span>
    DEBUG = <span class="hljs-literal">False</span>
    DEBUG_TB_ENABLED = <span class="hljs-literal">False</span>
</code></pre>
<p>In the above script, we have created a <code>Config</code> class and defined various attributes inside that. Also, we have created different child classes (as per different stages of development) that inherit the <code>Config</code> class.</p>
<p>Notice that we're using a few environment variables like <code>SECRET_KEY</code>, <code>DATABASE_URL</code>, and <code>APP_NAME</code>. Create a file named <code>.env</code> in the root directory and add the following content there:</p>
<pre><code class="lang-python">export SECRET_KEY=fdkjshfhjsdfdskfdsfdcbsjdkfdsdf
export DEBUG=<span class="hljs-literal">True</span>
export APP_SETTINGS=config.DevelopmentConfig
export DATABASE_URL=sqlite:///db.sqlite
export FLASK_APP=src
export FLASK_DEBUG=<span class="hljs-number">1</span>
export APP_NAME=<span class="hljs-string">"Flask User Authentication App"</span>
</code></pre>
<p>Apart from the <code>SECRET_KEY</code> , <code>DATABASE_URL</code> and <code>APP_NAME</code>, we've also exported <code>APP_SETTINGS</code>, <code>DEBUG</code>, <code>FLASK_APP</code>, and <code>FLASK_DEBUG</code>.</p>
<p>The <code>APP_SETTINGS</code> refers to one of the classes we created in the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>config.py</code></a> file. We set it to the current stage of the project.</p>
<p>The value of <code>FLASK_APP</code> is the name of the package we have created. Since the app is in the development stage, you can set the values of <code>DEBUG</code> and <code>FLASK_DEBUG</code> to <code>True</code> and <code>1</code>, respectively.</p>
<p>Run the following command to export all the environment variables from the <code>.env</code> file:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> .env
</code></pre>
<p>Next, we'll create a CLI application of the app so that we can later add custom commands if required.</p>
<p>Create a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>manage.py</code></a> file in the root directory of the application and add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask.cli <span class="hljs-keyword">import</span> FlaskGroup

<span class="hljs-keyword">from</span> src <span class="hljs-keyword">import</span> app

cli = FlaskGroup(app)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    cli()
</code></pre>
<p>Now, your basic application is ready. You can run it using the following command:</p>
<pre><code class="lang-bash">python manage.py run
</code></pre>
<p>Your file structure should look like below as of now:</p>
<pre><code class="lang-bash">flask-two-factor-auth/
├── src/
│   └── __init__.py
├── .env
├── config.py
└── manage.py
</code></pre>
<h2 id="heading-how-to-create-blueprints-for-accounts-and-core"><strong>How to Create Blueprints for Accounts and Core</strong></h2>
<p>As mentioned earlier, you'll use the concepts of blueprints in the project. Let's create two blueprints – <code>accounts_bp</code> and <code>core_bp</code> – in this section.</p>
<p>First, create a directory called <code>accounts</code> like this:</p>
<pre><code class="lang-bash">mkdir accounts
<span class="hljs-built_in">cd</span> accounts
</code></pre>
<p>Next, add an empty <code>__init__.py</code> file to convert it into a Python package. Now, create a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file inside the package where you'll store all your routes related to user authentication.</p>
<pre><code class="lang-bash">touch __init__.py views.py
</code></pre>
<p>Add the following code to the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Blueprint

accounts_bp = Blueprint(<span class="hljs-string">"accounts"</span>, __name__)
</code></pre>
<p>In the above script, you have created a blueprint called <code>accounts_bp</code> for the <code>accounts</code> package.</p>
<p>Similarly, you can create a <code>core</code> package in the root directory, and add a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file.</p>
<pre><code class="lang-bash">mkdir core
<span class="hljs-built_in">cd</span> core
touch __init__.py views.py
</code></pre>
<p>Now, add the following code to the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Blueprint

core_bp = Blueprint(<span class="hljs-string">"core"</span>, __name__)
</code></pre>
<blockquote>
<p>Note: If you're new to Flask Blueprints, make sure you go through <a target="_blank" href="https://ashutoshkrris.hashnode.dev/how-to-use-blueprints-to-organize-your-flask-apps">this tutorial</a> to learn more about how it works.</p>
</blockquote>
<p>Now, your file structure should look like what you see below:</p>
<pre><code class="lang-bash">flask-two-factor-auth/
├── src/
│   ├── accounts/
│   │   ├── __init__.py
│   │   └── views.py
│   ├── core/
│   │   ├── __init__.py
│   │   └── views.py
│   └── __init__.py
├── .env
├── config.py
└── manage.py
</code></pre>
<h2 id="heading-how-to-create-a-user-model"><strong>How to Create a User Model</strong></h2>
<p>Let's create a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>models.py</code></a> file inside the <code>accounts</code> package.</p>
<pre><code class="lang-bash">touch src/accounts/models.py
</code></pre>
<p>Inside the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>models.py</code></a> file, add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-keyword">import</span> pyotp
<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> UserMixin

<span class="hljs-keyword">from</span> src <span class="hljs-keyword">import</span> bcrypt, db
<span class="hljs-keyword">from</span> config <span class="hljs-keyword">import</span> Config


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">db.Model</span>):</span>

    __tablename__ = <span class="hljs-string">"users"</span>

    id = db.Column(db.Integer, primary_key=<span class="hljs-literal">True</span>)
    username = db.Column(db.String, unique=<span class="hljs-literal">True</span>, nullable=<span class="hljs-literal">False</span>)
    password = db.Column(db.String, nullable=<span class="hljs-literal">False</span>)
    created_at = db.Column(db.DateTime, nullable=<span class="hljs-literal">False</span>)
    is_two_factor_authentication_enabled = db.Column(
        db.Boolean, nullable=<span class="hljs-literal">False</span>, default=<span class="hljs-literal">False</span>)
    secret_token = db.Column(db.String, unique=<span class="hljs-literal">True</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, username, password</span>):</span>
        self.username = username
        self.password = bcrypt.generate_password_hash(password)
        self.created_at = datetime.now()
        self.secret_token = pyotp.random_base32()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_authentication_setup_uri</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> pyotp.totp.TOTP(self.secret_token).provisioning_uri(
            name=self.username, issuer_name=Config.APP_NAME)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_otp_valid</span>(<span class="hljs-params">self, user_otp</span>):</span>
        totp = pyotp.parse_uri(self.get_authentication_setup_uri())
        <span class="hljs-keyword">return</span> totp.verify(user_otp)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"&lt;user <span class="hljs-subst">{self.username}</span>&gt;"</span>
</code></pre>
<p>In the above code, you created a <code>User</code> model by inheriting the <code>db.Model</code> class. The <code>User</code> model consists of the following fields:</p>
<ul>
<li><p><code>id</code>: stores the primary key for the <code>users</code> table</p>
</li>
<li><p><code>username</code>: stores the username of the user</p>
</li>
<li><p><code>password</code>: stores the hashed password of the user</p>
</li>
<li><p><code>created_at</code>: stores the timestamp when the user was created</p>
</li>
<li><p><code>is_two_factor_authentication_enabled</code>: boolean flag that stores whether the user has activated two-factor authentication. Default value is <code>False</code>.</p>
</li>
<li><p><code>secret_token</code>: stores a unique token generated for each user, essential for implementing two-factor authentication.</p>
</li>
</ul>
<p>The constructor initializes the <code>User</code> object upon instantiation by accepting <code>username</code> and <code>password</code> parameters. It hashes the provided password using <code>bcrypt.generate_password_hash(password)</code>, records the current timestamp as the <code>created_at</code> value, and generates a unique <code>secret_token</code> using <code>pyotp.random_base32()</code> for 2FA setup.</p>
<p>The <code>get_authentication_setup_uri()</code> method generates a setup URI used by authenticator apps like Google Authenticator. It constructs a URI containing the user's username and the application's name (<a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>Config.APP</code></a><code>_NAME</code>) necessary for setting up two-factor authentication. The basic format of the URI is:</p>
<pre><code class="lang-bash">otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&amp;issuer=Example
</code></pre>
<p>where <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator">alice@google.com</a> is the username of the user and Example is the application's name.</p>
<p>Next up, the <code>is_otp_valid()</code> method verifies the one-time password (OTP) entered by the user during login. It parses the setup URI generated earlier, checks the validity of the provided OTP (<code>user_otp</code>), and returns <code>True</code> if the OTP matches, ensuring secure authentication.</p>
<p>Finally, the <code>__repr__</code> method provides a string representation of the <code>User</code> object, displaying the associated username when an instance of the class is printed or represented as a string.</p>
<h2 id="heading-how-to-add-flask-login"><strong>How to Add Flask-Login</strong></h2>
<p>The most important part of Flask-Login is the <code>LoginManager</code> class that lets your application and Flask-Login work together.</p>
<p>In the <code>src/__init__.py</code> file, add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> decouple <span class="hljs-keyword">import</span> config
<span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> LoginManager <span class="hljs-comment"># Add this line</span>
<span class="hljs-keyword">from</span> flask_migrate <span class="hljs-keyword">import</span> Migrate
<span class="hljs-keyword">from</span> flask_sqlalchemy <span class="hljs-keyword">import</span> SQLAlchemy

app = Flask(__name__)
app.config.from_object(config(<span class="hljs-string">"APP_SETTINGS"</span>))

login_manager = LoginManager() <span class="hljs-comment"># Add this line</span>
login_manager.init_app(app) <span class="hljs-comment"># Add this line</span>
db = SQLAlchemy(app)
migrate = Migrate(app, db)

<span class="hljs-comment"># Registering blueprints</span>
<span class="hljs-keyword">from</span> src.accounts.views <span class="hljs-keyword">import</span> accounts_bp
<span class="hljs-keyword">from</span> src.core.views <span class="hljs-keyword">import</span> core_bp

app.register_blueprint(accounts_bp)
app.register_blueprint(core_bp)
</code></pre>
<p>In the above script, we created and initialized the login manager in our app.</p>
<p>Next, we need to provide a <code>user_loader</code> callback. This callback is used to reload the user object from the user ID stored in the session. It should take the ID of a user, and return the corresponding user object.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> src.accounts.models <span class="hljs-keyword">import</span> User

<span class="hljs-meta">@login_manager.user_loader</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_user</span>(<span class="hljs-params">user_id</span>):</span>
    <span class="hljs-keyword">return</span> User.query.filter(User.id == int(user_id)).first()
</code></pre>
<p>The <code>User</code> model should implement the following properties and methods:</p>
<ul>
<li><p><code>is_authenticated</code>: This property returns True if the user is authenticated.</p>
</li>
<li><p><code>is_active</code>: This property returns True if this is an active user (the account is activated)</p>
</li>
<li><p><code>is_anonymous</code>: This property returns True if this is an anonymous user (actual users return False).</p>
</li>
<li><p><code>get_id()</code>: This method returns a string that uniquely identifies this user, and can be used to load the user from the <code>user_loader</code> callback.</p>
</li>
</ul>
<p>Now, we don't need to implement these explicitly. Instead, the Flask-Login provides a <code>UserMixin</code> class that contains the default implementations for all of these properties and methods. We just need to inherit it in the following way:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> UserMixin <span class="hljs-comment"># Add this line</span>

<span class="hljs-keyword">from</span> src <span class="hljs-keyword">import</span> bcrypt, db


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span>(<span class="hljs-params">UserMixin, db.Model</span>):</span> <span class="hljs-comment"># Change this line</span>
    ....
</code></pre>
<p>We can also customize the default login process in the <code>src/__init__.py</code> file.</p>
<p>The name of the login view can be set as <code>LoginManager.login_view</code>. The value refers to the function name that will handle the login process.</p>
<pre><code class="lang-python">login_manager.login_view = <span class="hljs-string">"accounts.login"</span>
</code></pre>
<p>To customize the message category, set <code>LoginManager.login_message_category</code>:</p>
<pre><code class="lang-python">login_manager.login_message_category = <span class="hljs-string">"danger"</span>
</code></pre>
<h2 id="heading-how-to-add-templates-and-static-files"><strong>How to Add Templates and Static Files</strong></h2>
<p>Let's create a CSS file called <code>styles.css</code> inside the <code>src/static</code> folder:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.error</span> {
  <span class="hljs-attribute">color</span>: red;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">text-decoration</span>: none;
}
</code></pre>
<p>Let's also create the basic templates inside the <code>src/templates</code> folder. Create a <code>_base.html</code> file and add the following code:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Two Factor Authentication<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- meta --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"author"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width,initial-scale=1"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- styles --&gt;</span>
    <span class="hljs-comment">&lt;!-- CSS only --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{url_for('static', filename="</span><span class="hljs-attr">styles.css</span>")}}"&gt;</span>
    {% block css %}{% endblock %}
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    {% include "navigation.html" %}

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>

      <span class="hljs-comment">&lt;!-- messages --&gt;</span>
      {% with messages = get_flashed_messages(with_categories=true) %}
      {% if messages %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span>
          {% for category, message in messages %}
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-{{ category }} alert-dismissible fade show"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
           {{message}}
           <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn-close"</span> <span class="hljs-attr">data-bs-dismiss</span>=<span class="hljs-string">"alert"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Close"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          {% endfor %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endif %}
      {% endwith %}

      <span class="hljs-comment">&lt;!-- child template --&gt;</span>
      {% block content %}{% endblock %}

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- scripts --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://code.jquery.com/jquery-3.7.1.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- JavaScript Bundle with Popper --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    {% block js %}{% endblock %}
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The <code>_base.html</code> is the parent HTML file that will be inherited by the other templates. We have added Bootstrap 5 support in the above file. We are also making use of Flask Flashes to show Bootstrap alerts in the app.</p>
<p>Let's also create a <code>navigation.html</code> file that contains the navbar of the app:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- Navigation --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar bg-dark navbar-expand-lg bg-body-tertiary p-3"</span> <span class="hljs-attr">data-bs-theme</span>=<span class="hljs-string">"dark"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-fluid"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('core.home') }}"</span>&gt;</span>Two-Factor Authentication App<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-toggler"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">data-bs-toggle</span>=<span class="hljs-string">"collapse"</span> <span class="hljs-attr">data-bs-target</span>=<span class="hljs-string">"#navbarSupportedContent"</span> <span class="hljs-attr">aria-controls</span>=<span class="hljs-string">"navbarSupportedContent"</span> <span class="hljs-attr">aria-expanded</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Toggle navigation"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-toggler-icon"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"collapse navbar-collapse"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"navbarSupportedContent"</span>&gt;</span>
      {% if current_user.is_authenticated %}
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('accounts.logout') }}"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-danger me-2"</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      {% endif %}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
</code></pre>
<p>Note that we have not yet created the views used above.</p>
<h2 id="heading-how-to-create-the-homepage"><strong>How to Create the Homepage</strong></h2>
<p>In this section, we'll first create a view function for the homepage inside the <code>core/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file. Add the following code there:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Blueprint, render_template
<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> login_required

core_bp = Blueprint(<span class="hljs-string">"core"</span>, __name__)


<span class="hljs-meta">@core_bp.route("/")</span>
<span class="hljs-meta">@login_required</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">home</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"core/index.html"</span>)
</code></pre>
<p>Notice that we have used the blueprint to add the route. We also added a <code>@login_required</code> middleware to prevent access for unauthenticated users.</p>
<p>Next, let's create an <code>index.html</code> file inside the <code>templates/core</code> folder, and add the following code:</p>
<pre><code class="lang-html">{% extends "_base.html" %}
{% block content %}

<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center"</span>&gt;</span>Welcome {{current_user.username}}!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

{% endblock %}
</code></pre>
<p>The HTML page will just have a welcome message for authenticated users.</p>
<p>Your file structure as of now should look like below:</p>
<pre><code class="lang-bash">flask-two-factor-auth/
├── src/
│   ├── accounts/
│   │   ├── __init__.py
│   │   └── views.py
│   ├── core/
│   │   ├── __init__.py
│   │   └── views.py
│   ├── static/
│   │   └── styles.css
│   ├── templates/
│   │   ├── core/
│   │   │   └── index.html
│   │   ├── _base.html
│   │   └── navigation.html
│   └── __init__.py
├── .env
├── config.py
└── manage.py
</code></pre>
<h2 id="heading-how-to-implement-user-registration"><strong>How to Implement User Registration</strong></h2>
<p>First of all, we'll create a registration form using Flask-WTF. Create a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>forms.py</code></a> file inside the <code>accounts</code> package and add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask_wtf <span class="hljs-keyword">import</span> FlaskForm
<span class="hljs-keyword">from</span> wtforms <span class="hljs-keyword">import</span> EmailField, PasswordField
<span class="hljs-keyword">from</span> wtforms.validators <span class="hljs-keyword">import</span> DataRequired, Email, EqualTo, Length

<span class="hljs-keyword">from</span> src.accounts.models <span class="hljs-keyword">import</span> User


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RegisterForm</span>(<span class="hljs-params">FlaskForm</span>):</span>
    username = StringField(
        <span class="hljs-string">"Username"</span>, validators=[DataRequired(), Length(min=<span class="hljs-number">6</span>, max=<span class="hljs-number">40</span>)]
    )
    password = PasswordField(
        <span class="hljs-string">"Password"</span>, validators=[DataRequired(), Length(min=<span class="hljs-number">6</span>, max=<span class="hljs-number">25</span>)]
    )
    confirm = PasswordField(
        <span class="hljs-string">"Repeat password"</span>,
        validators=[
            DataRequired(),
            EqualTo(<span class="hljs-string">"password"</span>, message=<span class="hljs-string">"Passwords must match."</span>),
        ],
    )

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validate</span>(<span class="hljs-params">self, extra_validators</span>):</span>
        initial_validation = super(RegisterForm, self).validate(extra_validators)
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> initial_validation:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
        user = User.query.filter_by(username=self.username.data).first()
        <span class="hljs-keyword">if</span> user:
            self.username.errors.append(<span class="hljs-string">"Username already registered"</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
        <span class="hljs-keyword">if</span> self.password.data != self.confirm.data:
            self.password.errors.append(<span class="hljs-string">"Passwords must match"</span>)
            <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
        <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
</code></pre>
<p>The <code>RegisterForm</code> extends the <code>FlaskForm</code> class and contains three fields – <code>username</code>, <code>password</code>, and <code>confirm</code>. We have added different validators such as <code>DataRequired</code>, <code>Length</code>, <code>Email</code>, and <code>EqualTo</code> to the respective fields.</p>
<p>We also defined a <code>validate()</code> method that is automatically called when the form is submitted.</p>
<p>Inside the method, we first perform the initial validation provided by FlaskForm. If that is successful, we perform our custom validation such as checking whether user is already registered and matching the password with the confirmed password. If there are any errors, we append the error message in the respective fields.</p>
<p>Now, let's use this form inside the HTML file. Create an <code>accounts</code> directory inside the <code>templates</code> folder and add a new file called <code>register.html</code> inside it. Add the following code:</p>
<pre><code class="lang-html">{% extends "_base.html" %}

{% block content %}

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-signin w-100 m-auto"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"form"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span>&gt;</span>
        {{ form.csrf_token }}
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h3 mb-3 fw-normal text-center"</span>&gt;</span>Please register<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-floating"</span>&gt;</span>
          {{ form.username(placeholder="username", class="form-control mb-2") }}
          {{ form.username.label }}
            {% if form.username.errors %}
              {% for error in form.username.errors %}
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                  {{ error }}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              {% endfor %}
            {% endif %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-floating"</span>&gt;</span>
          {{ form.password(placeholder="password", class="form-control mb-2") }}
          {{ form.password.label }}
            {% if form.password.errors %}
              {% for error in form.password.errors %}
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                  {{ error }}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              {% endfor %}
            {% endif %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-floating"</span>&gt;</span>
          {{ form.confirm(placeholder="Confirm Password", class="form-control mb-2") }}
          {{ form.confirm.label }}
            {% if form.confirm.errors %}
              {% for error in form.confirm.errors %}
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                  {{ error }}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              {% endfor %}
            {% endif %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-100 btn btn-lg btn-primary"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Sign up<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center mt-3"</span>&gt;</span>Already registered? <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('accounts.login') }}"</span>&gt;</span>Login now<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

{% endblock %}
</code></pre>
<p>In the above Jinja template, we make use of the form that we created and add relevant error-handling logic checks for validation errors in each field. Users can submit the form by clicking the "Sign up" button, and a link below the form allows already registered users to navigate to the login page for authentication.</p>
<p>Next, let's use this form in the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> to create a function to handle the registration process.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> .forms <span class="hljs-keyword">import</span> RegisterForm
<span class="hljs-keyword">from</span> src.accounts.models <span class="hljs-keyword">import</span> User
<span class="hljs-keyword">from</span> src <span class="hljs-keyword">import</span> db, bcrypt
<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> current_user
<span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Blueprint, flash, redirect, render_template, request, url_for

accounts_bp = Blueprint(<span class="hljs-string">"accounts"</span>, __name__)

HOME_URL = <span class="hljs-string">"core.home"</span>
SETUP_2FA_URL = <span class="hljs-string">"accounts.setup_two_factor_auth"</span>
VERIFY_2FA_URL = <span class="hljs-string">"accounts.verify_two_factor_auth"</span>

<span class="hljs-meta">@accounts_bp.route("/register", methods=["GET", "POST"])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">register</span>():</span>
    <span class="hljs-keyword">if</span> current_user.is_authenticated:
        <span class="hljs-keyword">if</span> current_user.is_two_factor_authentication_enabled:
            flash(<span class="hljs-string">"You are already registered."</span>, <span class="hljs-string">"info"</span>)
            <span class="hljs-keyword">return</span> redirect(url_for(HOME_URL))
        <span class="hljs-keyword">else</span>:
            flash(<span class="hljs-string">"You have not enabled 2-Factor Authentication. Please enable first to login."</span>, <span class="hljs-string">"info"</span>)
            <span class="hljs-keyword">return</span> redirect(url_for(SETUP_2FA_URL))
    form = RegisterForm(request.form)
    <span class="hljs-keyword">if</span> form.validate_on_submit():
        <span class="hljs-keyword">try</span>:
            user = User(username=form.username.data, password=form.password.data)
            db.session.add(user)
            db.session.commit()

            login_user(user)
            flash(<span class="hljs-string">"You are registered. You have to enable 2-Factor Authentication first to login."</span>, <span class="hljs-string">"success"</span>)

            <span class="hljs-keyword">return</span> redirect(url_for(SETUP_2FA_URL))
        <span class="hljs-keyword">except</span> Exception:
            db.session.rollback()
            flash(<span class="hljs-string">"Registration failed. Please try again."</span>, <span class="hljs-string">"danger"</span>)

    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"accounts/register.html"</span>, form=form)
</code></pre>
<p>The route begins by checking if the current user is already authenticated. If so, it verifies whether 2FA is enabled for the user. If 2FA is already enabled, a message informs the user that they're already registered, redirecting them to the home URL. However, if the user is authenticated but 2FA is not enabled, a flash message prompts the user to enable 2FA first before logging in, redirecting them to the 2FA setup URL.</p>
<p>If the user is not authenticated or has not yet registered 2FA, the code initializes a registration form and proceeds to validate the form data on submission. Upon successful form validation, we create a new <code>User</code> object with the provided username and password and save it to the database.</p>
<p>Upon successful user registration, the newly registered user is logged in. A success message flashes, notifying the user of successful registration and prompting them to enable 2FA before logging in. Subsequently, the user is redirected to the 2FA setup URL to enable 2FA.</p>
<h2 id="heading-how-to-implement-user-login"><strong>How to Implement User Login</strong></h2>
<p>First, let's create a login form in the <code>accounts/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>forms.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoginForm</span>(<span class="hljs-params">FlaskForm</span>):</span>
    username = StringField(<span class="hljs-string">"Username"</span>, validators=[DataRequired()])
    password = PasswordField(<span class="hljs-string">"Password"</span>, validators=[DataRequired()])
</code></pre>
<p>The form is similar to the registration form but it has only two fields – <code>username</code> and <code>password</code>.</p>
<p>Now, let's use this form inside a new HTML file called <code>login.html</code> created inside the <code>templates/accounts</code> directory. Add the following code:</p>
<pre><code class="lang-html">{% extends "_base.html" %}

{% block content %}

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-signin w-100 m-auto"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"form"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span>&gt;</span>
        {{ form.csrf_token }}
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h3 mb-3 fw-normal text-center"</span>&gt;</span>Please sign in<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-floating"</span>&gt;</span>
          {{ form.username(placeholder="username", class="form-control mb-2") }}
          {{ form.username.label }}
            {% if form.username.errors %}
              {% for error in form.username.errors %}
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                {{ error }}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              {% endfor %}
            {% endif %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-floating"</span>&gt;</span>
          {{ form.password(placeholder="password", class="form-control mb-2") }}
          {{ form.password.label }}
            {% if form.password.errors %}
              {% for error in form.password.errors %}
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                  {{ error }}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              {% endfor %}
            {% endif %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-100 btn btn-lg btn-primary"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Sign in<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center mt-3"</span>&gt;</span>New User? <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('accounts.register') }}"</span>&gt;</span>Register now<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

{% endblock %}
</code></pre>
<p>The above HTML file is also similar to the <code>register.html</code> file but with just two fields for the username and password.</p>
<p>Next, let's create a view function to handle the login process inside the <code>accounts/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> .forms <span class="hljs-keyword">import</span> LoginForm, RegisterForm

<span class="hljs-meta">@accounts_bp.route("/login", methods=["GET", "POST"])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">login</span>():</span>
    <span class="hljs-keyword">if</span> current_user.is_authenticated:
        <span class="hljs-keyword">if</span> current_user.is_two_factor_authentication_enabled:
            flash(<span class="hljs-string">"You are already logged in."</span>, <span class="hljs-string">"info"</span>)
            <span class="hljs-keyword">return</span> redirect(url_for(HOME_URL))
        <span class="hljs-keyword">else</span>:
            flash(<span class="hljs-string">"You have not enabled 2-Factor Authentication. Please enable first to login."</span>, <span class="hljs-string">"info"</span>)
            <span class="hljs-keyword">return</span> redirect(url_for(SETUP_2FA_URL))

    form = LoginForm(request.form)
    <span class="hljs-keyword">if</span> form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        <span class="hljs-keyword">if</span> user <span class="hljs-keyword">and</span> bcrypt.check_password_hash(user.password, request.form[<span class="hljs-string">"password"</span>]):
            login_user(user)
            <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> current_user.is_two_factor_authentication_enabled:
                flash(
                    <span class="hljs-string">"You have not enabled 2-Factor Authentication. Please enable first to login."</span>, <span class="hljs-string">"info"</span>)
                <span class="hljs-keyword">return</span> redirect(url_for(SETUP_2FA_URL))
            <span class="hljs-keyword">return</span> redirect(url_for(VERIFY_2FA_URL))
        <span class="hljs-keyword">elif</span> <span class="hljs-keyword">not</span> user:
            flash(<span class="hljs-string">"You are not registered. Please register."</span>, <span class="hljs-string">"danger"</span>)
        <span class="hljs-keyword">else</span>:
            flash(<span class="hljs-string">"Invalid username and/or password."</span>, <span class="hljs-string">"danger"</span>)
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"accounts/login.html"</span>, form=form)
</code></pre>
<p>The route starts by checking if the current user is already authenticated. If the user is authenticated and 2FA is enabled, a message informs the user they're already logged in, redirecting them to the home URL. If the user is authenticated but 2FA isn't enabled, a flash message prompts the user to enable 2FA before logging in, redirecting them to the 2FA setup URL.</p>
<p>If the user isn't authenticated, the code initializes a login form and validates the form data upon submission. Upon successful validation, it queries the database to find a user matching the provided username. If the user exists and the password matches the hashed password stored in the database, the user is logged in.</p>
<p>Additionally, if 2FA isn't enabled for the current user after successful login, a flash message prompts the user to enable 2FA before proceeding, redirecting them to the 2FA setup URL. If the login is successful and 2FA is enabled, the user is redirected to the 2FA verification URL.</p>
<p>If the user isn't registered, a flash message informs them to register. If there's a mismatch in the provided username or password, another flash message notifies the user of invalid credentials.</p>
<h2 id="heading-how-to-log-out-the-users"><strong>How to Log Out the Users</strong></h2>
<p>Logging out the user is a very simple process. You just need to create a view function for it inside the <code>accounts/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> login_required, login_user, logout_user


<span class="hljs-meta">@accounts_bp.route("/logout")</span>
<span class="hljs-meta">@login_required</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">logout</span>():</span>
    logout_user()
    flash(<span class="hljs-string">"You were logged out."</span>, <span class="hljs-string">"success"</span>)
    <span class="hljs-keyword">return</span> redirect(url_for(<span class="hljs-string">"accounts.login"</span>))
</code></pre>
<p>The <code>Flask-Login</code> library contains a <code>logout_user</code> method that removes the user from the session. We used the <code>@login_required</code> decorator so that only authenticated users could logout.</p>
<h2 id="heading-how-to-add-the-setup-2fa-page"><strong>How to Add the Setup 2FA Page</strong></h2>
<p>Up until now, we have been redirecting the users to the setup 2FA page whenever the 2FA is not enabled in their accounts, but we haven't implemented it yet. Let's do that in this section.</p>
<p>Let's start with the route for the page:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> src.utils <span class="hljs-keyword">import</span> get_b64encoded_qr_image

<span class="hljs-meta">@accounts_bp.route("/setup-2fa")</span>
<span class="hljs-meta">@login_required</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">setup_two_factor_auth</span>():</span>
    secret = current_user.secret_token
    uri = current_user.get_authentication_setup_uri()
    base64_qr_image = get_b64encoded_qr_image(uri)
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"accounts/setup-2fa.html"</span>, secret=secret, qr_image=base64_qr_image)
</code></pre>
<p>The route, created inside <code>accounts/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a>, ensures that only authenticated users can access it using the <code>@login_required</code> decorator.</p>
<p>Upon accessing this route, the function retrieves the current user's <code>secret_token</code> for 2FA setup and generates a URI through <code>current_user.get_authentication_setup_uri()</code> to configure an authenticator app like Google Authenticator.</p>
<p>It also uses <code>get_b64encoded_qr_image(uri)</code> to obtain a Base64-encoded QR code image representing this setup URI. We will define it below.</p>
<p>Finally, it renders the <code>setup-2fa.html</code> template, passing the user's <code>secret_token</code> and the Base64-encoded QR image to the template for users to scan it.</p>
<p>Next, create a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>utils.py</code></a> file in the <code>src</code> directory and add the following code to <a target="_blank" href="https://blog.ashutoshkrris.in/5-quick-python-projects#heading-qr-codes-in-python">generate the QR</a>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO
<span class="hljs-keyword">import</span> qrcode
<span class="hljs-keyword">from</span> base64 <span class="hljs-keyword">import</span> b64encode


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_b64encoded_qr_image</span>(<span class="hljs-params">data</span>):</span>
    print(data)
    qr = qrcode.QRCode(version=<span class="hljs-number">1</span>, box_size=<span class="hljs-number">10</span>, border=<span class="hljs-number">5</span>)
    qr.add_data(data)
    qr.make(fit=<span class="hljs-literal">True</span>)
    img = qr.make_image(fill_color=<span class="hljs-string">'black'</span>, back_color=<span class="hljs-string">'white'</span>)
    buffered = BytesIO()
    img.save(buffered)
    <span class="hljs-keyword">return</span> b64encode(buffered.getvalue()).decode(<span class="hljs-string">"utf-8"</span>)
</code></pre>
<p>Remember the <code>qrcode</code> library we installed at the beginning of the tutorial? This is where we're going to use it.</p>
<p>Upon receiving <code>data</code> as input, representing the content to be embedded within the QR code, the function initializes a QRCode object using the <code>qrcode</code> library. It adds the provided data to this QR code instance and generates the QR code. The code then converts this QR code into an image representation.</p>
<p>Using a BytesIO object, it stores this image in memory. The function proceeds to encode the content of this in-memory buffer, representing the QR code image, into Base64 format. Finally, it returns this Base64-encoded string, encapsulating the QR code image, ready for transmission or display in various applications.</p>
<p>Next, let's create the <code>setup-2fa.html</code> page inside the <code>templates/accounts</code> folder, and add the following content:</p>
<pre><code class="lang-html">{% extends "_base.html" %}

{% block content %}

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-signin w-100 m-auto"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"form"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h5</span>&gt;</span>Instructions!<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Download <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&amp;hl=en&amp;gl=US"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>&gt;</span>Google Authenticator<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> on your mobile.<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Set up a new authenticator.<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Once you have scanned the QR, please click <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('accounts.verify_two_factor_auth') }}"</span>&gt;</span>here.<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"data:image/png;base64, {{ qr_image }}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Secret Token"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width:200px;height:200px"</span>/&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"secret"</span>&gt;</span>Secret Token<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"secret"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"{{ secret }}"</span> <span class="hljs-attr">readonly</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center mt-2"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"copySecret()"</span>&gt;</span>
            Copy Secret
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-4 text-center"</span>&gt;</span>
          Once you have scanned the QR, please click <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ url_for('accounts.verify_two_factor_auth') }}"</span>&gt;</span>here<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>.
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

{% endblock %}

{% block js %}
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">copySecret</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> copyText = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"secret"</span>);
    copyText.select();
    copyText.setSelectionRange(<span class="hljs-number">0</span>, <span class="hljs-number">99999</span>); <span class="hljs-comment">/*For mobile devices*/</span>
    <span class="hljs-built_in">document</span>.execCommand(<span class="hljs-string">"copy"</span>);
    alert(<span class="hljs-string">"Successfully copied TOTP secret token!"</span>);
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
{% endblock %}
</code></pre>
<p>We added some instructions on the page for the users to follow. These instructions provide clear steps for users to enable 2FA: directing them to download the Google Authenticator app via a link, guiding the setup process within the app, and prompting users to proceed by clicking a link after scanning the displayed QR code.</p>
<p>Displaying the QR code is central to the setup process. The template embeds the QR code image using an <code>&lt;img&gt;</code> tag with its source set to a Base64-encoded string (<code>{{ qr_image }}</code>). This image represents the secret key essential for the 2FA setup.</p>
<p>We also show the secret key in read-only mode, allowing users to view the key without being able to modify it. We have added a copy button to make it easier for the users to copy the key.</p>
<p>Moreover, we have added a link to the 2FA verification page guiding users to proceed with the setup process after scanning the QR code. We will implement this functionality in the next section.</p>
<p>Here's how your page looks right now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-26-010925.png" alt="2FA Setup Page" /></p>
<h2 id="heading-how-to-add-a-2fa-verification-page"><strong>How to Add a 2FA Verification Page</strong></h2>
<p>In this section, let's implement the 2FA verification. To start with, we will require an OTP form where users can enter their OTP. Add the following content to the <code>accounts/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>forms.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TwoFactorForm</span>(<span class="hljs-params">FlaskForm</span>):</span>
    otp = StringField(<span class="hljs-string">'Enter OTP'</span>, validators=[
                      InputRequired(), Length(min=<span class="hljs-number">6</span>, max=<span class="hljs-number">6</span>)])
</code></pre>
<p>The <code>TwoFactorForm</code> contains just one field (<code>otp</code>) to get the OTP from the users.</p>
<p>Now, let's use this form in the <code>verify-2fa.html</code> file inside the <code>templates/accounts</code> folder:</p>
<pre><code class="lang-html">{% extends "_base.html" %}

{% block content %}

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-signin w-100 m-auto"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"form"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span>&gt;</span>
        {{ form.csrf_token }}
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h3 mb-3 fw-normal text-center"</span>&gt;</span>Enter OTP<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-floating"</span>&gt;</span>
          {{ form.otp(placeholder="OTP", class="form-control mb-2") }}
          {{ form.otp.label }}
            {% if form.otp.errors %}
              {% for error in form.otp.errors %}
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                {{ error }}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              {% endfor %}
            {% endif %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"w-100 btn btn-lg btn-primary"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Verify<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-4"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

{% endblock %}
</code></pre>
<p>The Jinja template essentially contains a form with one field for OTP and a verify button.</p>
<p>Let's create the route that handles the submission of this form inside the <code>accounts/</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>views.py</code></a> file:</p>
<pre><code class="lang-python"><span class="hljs-meta">@accounts_bp.route("/verify-2fa", methods=["GET", "POST"])</span>
<span class="hljs-meta">@login_required</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">verify_two_factor_auth</span>():</span>
    form = TwoFactorForm(request.form)
    <span class="hljs-keyword">if</span> form.validate_on_submit():
        <span class="hljs-keyword">if</span> current_user.is_otp_valid(form.otp.data):
            <span class="hljs-keyword">if</span> current_user.is_two_factor_authentication_enabled:
                flash(<span class="hljs-string">"2FA verification successful. You are logged in!"</span>, <span class="hljs-string">"success"</span>)
                <span class="hljs-keyword">return</span> redirect(url_for(HOME_URL))
            <span class="hljs-keyword">else</span>:
                <span class="hljs-keyword">try</span>:
                    current_user.is_two_factor_authentication_enabled = <span class="hljs-literal">True</span>
                    db.session.commit()
                    flash(<span class="hljs-string">"2FA setup successful. You are logged in!"</span>, <span class="hljs-string">"success"</span>)
                    <span class="hljs-keyword">return</span> redirect(url_for(HOME_URL))
                <span class="hljs-keyword">except</span> Exception:
                    db.session.rollback()
                    flash(<span class="hljs-string">"2FA setup failed. Please try again."</span>, <span class="hljs-string">"danger"</span>)
                    <span class="hljs-keyword">return</span> redirect(url_for(VERIFY_2FA_URL))
        <span class="hljs-keyword">else</span>:
            flash(<span class="hljs-string">"Invalid OTP. Please try again."</span>, <span class="hljs-string">"danger"</span>)
            <span class="hljs-keyword">return</span> redirect(url_for(VERIFY_2FA_URL))
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> current_user.is_two_factor_authentication_enabled:
            flash(
                <span class="hljs-string">"You have not enabled 2-Factor Authentication. Please enable it first."</span>, <span class="hljs-string">"info"</span>)
        <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"accounts/verify-2fa.html"</span>, form=form)
</code></pre>
<p>The route starts by initializing a form (<code>TwoFactorForm</code>) meant for 2FA verification using the data obtained from the request. Upon form submission, the code proceeds with several conditional checks to validate the OTP entered by the user.</p>
<p>Once the form has been successfully submitted and validated, the code verifies the authenticity of the OTP using <code>current_</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>user.is</code></a><code>_otp_valid(</code><a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-two-factor-authentication-in-your-flask-app/#overview-of-pyotp-and-google-authenticator"><code>form.otp.data</code></a><code>)</code>, which checks if the entered OTP is valid for the current user. If the OTP is valid, the code executes the following logic:</p>
<ul>
<li><p>If the provided OTP is valid and 2FA is already enabled for the user, a success message is flashed indicating successful 2FA verification, and the user is redirected to the home URL.</p>
</li>
<li><p>If the OTP is valid but 2FA isn't enabled for the user, it attempts to enable 2FA for that user. Upon successful activation, a success message flashes, and the user is redirected to the home URL.</p>
</li>
</ul>
<p>Furthermore, if the OTP entered by the user is invalid, the code flashes an error message indicating an invalid OTP and redirects the user back to the 2FA verification URL to retry the verification process.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-26-011107.png" alt="2FA Verification Page" /></p>
<p>With this, we have completed the implementation of all the features! 🎉</p>
<h2 id="heading-how-to-run-the-completed-app-for-the-first-time"><strong>How to Run the Completed App for the First Time</strong></h2>
<p>Now that our application is ready, you can first migrate the database, and then run the app.</p>
<p>To initialize the database (create a migration repository), use the command:</p>
<pre><code class="lang-bash">flask db init
</code></pre>
<p>To migrate the database changes, use the command:</p>
<pre><code class="lang-bash">flask db migrate
</code></pre>
<p>To apply the migrations, use the command:</p>
<pre><code class="lang-bash">flask db upgrade
</code></pre>
<p>Since this is the first time we're running our app, you'll need to run all the above commands. Later, whenever you make changes to the database, you'll just need to run the last two commands.</p>
<p>After that, you can run your application using the command:</p>
<pre><code class="lang-python">python manage.py run
</code></pre>
<p>Since we have completed the development, here's how your file structure should look like:</p>
<pre><code class="lang-bash">flask-two-factor-auth/
├── migrations/
├── src/
│   ├── accounts/
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── models.py
│   │   └── views.py
│   ├── core/
│   │   ├── __init__.py
│   │   └── views.py
│   ├── static/
│   │   └── styles.css
│   ├── templates/
│   │   ├── accounts/
│   │   │   ├── login.html
│   │   │   ├── register.html
│   │   │   ├── setup-2fa.html
│   │   │   └── verify-2fa.html
│   │   ├── core/
│   │   │   └── index.html
│   │   ├── _base.html
│   │   └── navigation.html
│   ├── __init__.py
│   └── utils.py
├── .env
├── config.py
└── manage.py
</code></pre>
<h2 id="heading-wrapping-up"><strong>Wrapping up</strong></h2>
<p>In this tutorial, you learned how to set up two-factor authentication in your Flask app using PyOTP.</p>
<p>Here's the link to the <a target="_blank" href="https://github.com/ashutoshkrris/Flask-Two-Factor-Authentication">GitHub repository</a>. Feel free to check it out whenever you're stuck.</p>
<p>Here are some other tutorials I wrote about authentication, email verification, and OTPs that you might enjoy:</p>
<ul>
<li><p><a target="_blank" href="https://blog.ashutoshkrris.in/how-to-set-up-basic-user-authentication-in-a-flask-app">How to Set Up Basic User Authentication in a Flask App</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/how-to-setup-user-authentication-in-flask/">How to Set Up Email Verification in a Flask App</a></p>
</li>
<li><p><a target="_blank" href="https://blog.ashutoshkrris.in/how-to-generate-otps-using-pyotp-in-python">How To Generate OTPs Using PyOTP in Python</a></p>
</li>
</ul>
<p>Thank you for reading. I hope you found this article useful. You can follow me on <a target="_blank" href="https://twitter.com/ashutoshkrris">Twitter</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Python One-Liners - Code Hacks You Should Know]]></title><description><![CDATA[Python's beauty lies in its simplicity and readability. And mastering the art of writing concise yet powerful code can significantly enhance your productivity as a developer. I'm talking about really short lines of code that do big things.
In this ar...]]></description><link>https://blog.ashutoshkrris.in/python-one-liners-code-hacks-you-should-know</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/python-one-liners-code-hacks-you-should-know</guid><category><![CDATA[Python]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Programming Tips]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Thu, 30 Nov 2023 02:16:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1701310388682/e7385d7a-ffe1-463b-a839-7210269ed822.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python's beauty lies in its simplicity and readability. And mastering the art of writing concise yet powerful code can significantly enhance your productivity as a developer. I'm talking about really short lines of code that do big things.</p>
<p>In this article, we'll explore 8 essential Python one-liners that every Pythonista should have in their toolkit. From list comprehensions to lambda functions and beyond, these techniques offer elegant solutions to common programming challenges, helping you write cleaner, more efficient code.</p>
<h2 id="heading-list-comprehension"><strong>List Comprehension</strong></h2>
<p>List comprehension is a Pythonic way to create lists with a single line of code. It offers a concise alternative to traditional loops, enabling you to generate lists quickly and efficiently.</p>
<p>Let's say you want to create a list containing squares of numbers from 0 to 9. Using a traditional loop, you'd do it like this:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using a traditional loop</span>
squared_numbers = []
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>):
    squared_numbers.append(i ** <span class="hljs-number">2</span>)
print(squared_numbers)
</code></pre>
<p>The traditional loop method requires more lines of code and explicitly defines the iteration process, appending each squared number to the list step by step.</p>
<p>On the other hand, list comprehension can achieve the same result in a single line, making the code more concise and readable. It condenses the loop into a clear, compact structure, generating the squared numbers directly into a list.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using list comprehension</span>
squared_numbers = [i ** <span class="hljs-number">2</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)]
print(squared_numbers)
</code></pre>
<p>You can use list comprehensions when you need to apply a simple operation to every element in a sequence, such as transforming a list of numbers or strings.</p>
<p>You can learn how you can pack and destructure lists in Python <a target="_blank" href="https://blog.ashutoshkrris.in/mastering-list-destructuring-and-packing-in-python-a-comprehensive-guide">here</a>.</p>
<h2 id="heading-lambda-functions"><strong>Lambda Functions</strong></h2>
<p><a target="_blank" href="https://blog.ashutoshkrris.in/mastering-lambdas-a-guide-to-anonymous-functions-in-python">Lambda functions</a>, also known as anonymous functions, allow you to create small, throwaway functions without explicitly defining them with <code>def</code>. They are particularly useful in scenarios where a function is needed for a short operation.</p>
<p>First, let's look at an example using <code>def</code>:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using def</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_numbers</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x + y

print(add_numbers(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>))
</code></pre>
<p>In this code, the <code>def</code> keyword is used to define a named function <code>add_numbers</code> explicitly. It takes an argument <code>x</code> and <code>y</code> and returns the sum of them. This traditional approach provides a named function that can be called multiple times.</p>
<p>But when you need a function just for one-time usage, you can just define an anonymous function using the <code>lambda</code> keyword like this:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using Lambda</span>
add = <span class="hljs-keyword">lambda</span> x, y: x + y
print(add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>))
</code></pre>
<p>It achieves the same result as <code>add_numbers</code> but in a single line without assigning a name explicitly. Lambda functions are useful for short, throwaway functions that are used infrequently or as part of other expressions.</p>
<h2 id="heading-map-and-filter"><strong>Map and Filter</strong></h2>
<p>The <code>map</code> and <code>filter</code> functions are powerful tools for working with iterables, allowing concise manipulation and filtering of data.</p>
<p>Let's say you have a list of strings and you want to convert each item of the list into uppercase.</p>
<pre><code class="lang-python">fruits = [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'banana'</span>, <span class="hljs-string">'cherry'</span>]
upper_case_loop = []
<span class="hljs-keyword">for</span> fruit <span class="hljs-keyword">in</span> fruits:
    upper_case_loop.append(fruit.upper())
print(upper_case_loop)
</code></pre>
<p>Now, you can achieve the same using the <code>map</code> function:</p>
<pre><code class="lang-python">upper_case = list(map(<span class="hljs-keyword">lambda</span> x: x.upper(), [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'banana'</span>, <span class="hljs-string">'cherry'</span>]))
</code></pre>
<p>You can utilize <code>map</code> when you need to perform an operation on every element of an iterable. <code>filter</code> is handy for selectively choosing elements based on a condition.</p>
<p>You can learn more about the <code>map</code>, <code>filter</code> and <code>reduce</code> functions <a target="_blank" href="https://blog.ashutoshkrris.in/mastering-lambdas-a-guide-to-anonymous-functions-in-python#heading-using-lambda-functions-as-arguments-in-higher-order-functions-map-filter-reduce">here</a>.</p>
<h2 id="heading-ternary-operator"><strong>Ternary Operator</strong></h2>
<p>The ternary operator provides a condensed way to write conditional statements in a single line, enhancing code readability.</p>
<p>Let's say, you have a number and you want to check if it's even or odd. You can do it using the traditional if condition as below:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Traditional if</span>
result = <span class="hljs-literal">None</span>
num = <span class="hljs-number">5</span>
<span class="hljs-keyword">if</span> num % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>:
    result = <span class="hljs-string">"Even"</span>
<span class="hljs-keyword">else</span>:
    result = <span class="hljs-string">"Odd"</span>
</code></pre>
<p>But you can achieve the same results in a single line using the ternary operator:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Ternary Operator</span>
num = <span class="hljs-number">7</span>
result = <span class="hljs-string">"Even"</span> <span class="hljs-keyword">if</span> num % <span class="hljs-number">2</span> == <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"Odd"</span>
</code></pre>
<p>When you need to assign values based on conditions, especially in situations requiring simple if-else checks, the ternary operator shines.</p>
<h2 id="heading-zip-function"><strong>Zip Function</strong></h2>
<p>The <code>zip</code> function enables you to combine multiple iterables element-wise, forming tuples of corresponding elements.</p>
<p>Let's assume you have two lists: one containing the names of students and the other containing their respective grades for a specific assignment.</p>
<pre><code class="lang-python">students = [<span class="hljs-string">'Dilli'</span>, <span class="hljs-string">'Vikram'</span>, <span class="hljs-string">'Rolex'</span>, <span class="hljs-string">'Leo'</span>]
grades = [<span class="hljs-number">85</span>, <span class="hljs-number">92</span>, <span class="hljs-number">78</span>, <span class="hljs-number">88</span>]
</code></pre>
<p>Now, you want to create a report that pairs each student's name with their grade for easy comprehension or further analysis. You can do it by iterating over the list and appending them to a new list as below:</p>
<pre><code class="lang-python">students = [<span class="hljs-string">'Dilli'</span>, <span class="hljs-string">'Vikram'</span>, <span class="hljs-string">'Rolex'</span>, <span class="hljs-string">'Leo'</span>]
grades = [<span class="hljs-number">85</span>, <span class="hljs-number">92</span>, <span class="hljs-number">78</span>, <span class="hljs-number">88</span>]

student_grade_pairs = []
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(students)):
    student_grade_pairs.append((students[i], grades[i]))

print(student_grade_pairs)
</code></pre>
<p>The above loop method manually pairs elements from two lists by iterating through their indices, accessing elements at the same positions, and appending tuples of those elements into a new list <code>student_grade_pairs</code>.</p>
<p>But, what if I tell you that we can achieve the same pairing effect in one line using the <code>zip</code> function as below:</p>
<pre><code class="lang-python">students = [<span class="hljs-string">'Dilli'</span>, <span class="hljs-string">'Vikram'</span>, <span class="hljs-string">'Rolex'</span>, <span class="hljs-string">'Leo'</span>]
grades = [<span class="hljs-number">85</span>, <span class="hljs-number">92</span>, <span class="hljs-number">78</span>, <span class="hljs-number">88</span>]

student_grade_pairs = list(zip(students, grades))
print(student_grade_pairs)
</code></pre>
<p>The <code>zip</code> function elegantly combines elements from both lists, creating pairs of corresponding elements as tuples. The result <code>student_grade_pairs</code> is a list of tuples, where each tuple contains an element from the grades list paired with the corresponding element from the <code>students</code> list.</p>
<p>You can learn more about the <code>zip</code>  function <a target="_blank" href="https://blog.ashutoshkrris.in/zipping-through-python-a-comprehensive-guide-to-the-zip-function">here</a>.</p>
<h2 id="heading-enumerate-function"><strong>Enumerate Function</strong></h2>
<p>The <code>enumerate</code> function offers a concise way to iterate over a sequence while keeping track of the index.</p>
<p>Let's say you're developing a feature where users can add items to their shopping list, and you want to display the items along with their position or index in the list for easy reference.</p>
<p>You can do it using a traditional for-loop as below:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Simulating a grocery list</span>
grocery_list = [<span class="hljs-string">'Apples'</span>, <span class="hljs-string">'Milk'</span>, <span class="hljs-string">'Bread'</span>, <span class="hljs-string">'Eggs'</span>, <span class="hljs-string">'Cheese'</span>]

<span class="hljs-comment"># Displaying the grocery list with indices</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(grocery_list)):
    print(<span class="hljs-string">f"<span class="hljs-subst">{i}</span>. <span class="hljs-subst">{grocery_list[i]}</span>"</span>)
</code></pre>
<p>The traditional loop with manual indexing involves using <code>range</code> along with <code>len</code> to generate indices that are then used to access elements in the <code>grocery_list</code> list. This method requires more code and is less readable due to the explicit handling of indices.</p>
<p>The <code>enumerate</code> function simplifies the process by directly providing both indices and elements from the <code>grocery_list</code> list.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Simulating a grocery list</span>
grocery_list = [<span class="hljs-string">'Apples'</span>, <span class="hljs-string">'Milk'</span>, <span class="hljs-string">'Bread'</span>, <span class="hljs-string">'Eggs'</span>, <span class="hljs-string">'Cheese'</span>]

<span class="hljs-comment"># Displaying the grocery list with indices</span>
<span class="hljs-keyword">for</span> index, item <span class="hljs-keyword">in</span> enumerate(grocery_list):
    print(<span class="hljs-string">f"<span class="hljs-subst">{index}</span>. <span class="hljs-subst">{item}</span>"</span>)
</code></pre>
<p>It's concise, readable, and more Pythonic, eliminating the need for manual index handling and making the code cleaner. This approach is generally preferred for its simplicity and clarity in obtaining indices and elements from an iterable.</p>
<h2 id="heading-string-join"><strong>String Join</strong></h2>
<p>The <code>join</code> method is a clean way to concatenate strings from an iterable into a single string.</p>
<p>Suppose you have a list of words and want to create a sentence by joining these words using traditional concatenation. You'd do it as below:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using traditional concatenation</span>
words = [<span class="hljs-string">'Python'</span>, <span class="hljs-string">'is'</span>, <span class="hljs-string">'awesome'</span>, <span class="hljs-string">'and'</span>, <span class="hljs-string">'powerful'</span>]

sentence = <span class="hljs-string">''</span>
<span class="hljs-keyword">for</span> word <span class="hljs-keyword">in</span> words:
    sentence += word + <span class="hljs-string">' '</span>

print(sentence.strip())  <span class="hljs-comment"># Strip to remove the trailing space</span>
</code></pre>
<p>In the traditional concatenation method, a loop iterates through the list of words, and each word is concatenated with a space. However, this approach requires creating a new string for each concatenation operation, which might not be efficient for larger strings due to string immutability.</p>
<p>The <code>join</code> method, on the other hand, is more efficient and concise. It joins the elements of the list using the specified separator (in this case, a space), creating the sentence in a single operation.</p>
<pre><code class="lang-python">.<span class="hljs-comment"># Using join method</span>
words = [<span class="hljs-string">'Python'</span>, <span class="hljs-string">'is'</span>, <span class="hljs-string">'awesome'</span>, <span class="hljs-string">'and'</span>, <span class="hljs-string">'powerful'</span>]

sentence = <span class="hljs-string">' '</span>.join(words)
print(sentence)
</code></pre>
<p>This method is generally the preferred way to join strings in Python due to its efficiency and readability.</p>
<h2 id="heading-unpacking-lists"><strong>Unpacking Lists</strong></h2>
<p>Python's unpacking feature allows for efficient assignment of elements from iterables to variables.</p>
<p>Suppose you have a list of numbers, and you want to assign each number to separate variables using traditional indexing.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using traditional unpacking</span>
numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]

a = numbers[<span class="hljs-number">0</span>]
b = numbers[<span class="hljs-number">1</span>]
c = numbers[<span class="hljs-number">2</span>]

print(a, b, c)
</code></pre>
<p>In the traditional unpacking method, individual elements from the list are accessed and assigned to separate variables by explicitly indexing each element. This method is more verbose and requires knowing the number of elements in advance.</p>
<p>Now, let's accomplish the same using the <code>*</code> operator for unpacking the list into variables.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using * operator for unpacking</span>
numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]

a, b, c = numbers

print(a, b, c)
</code></pre>
<p>You can learn more about the <code>*</code> operator and list unpacking in <a target="_blank" href="https://blog.ashutoshkrris.in/mastering-list-destructuring-and-packing-in-python-a-comprehensive-guide#heading-destructuring-assignment">this tutorial</a>.</p>
<h2 id="heading-should-you-always-use-one-liners"><strong>Should You Always Use One-Liners?</strong></h2>
<p>While Python one-liners offer conciseness and elegance, there are considerations to keep in mind before applying them universally:</p>
<ol>
<li><p><strong>Readability</strong>: One-liners might sacrifice readability for crispness. Complex one-liners can be hard to understand, especially for newcomers or when revisiting code after some time.</p>
</li>
<li><p><strong>Maintainability</strong>: Overusing one-liners, especially complex ones, can make code maintenance challenging. Debugging and modifying concise code might be more difficult.</p>
</li>
<li><p><strong>Performance</strong>: In certain scenarios, one-liners might not be the most performant solution. These concise expressions may consume more resources, such as memory or CPU, and their underlying operations might have higher time complexity, affecting efficiency, especially with large datasets or intensive computations.</p>
</li>
<li><p><strong>Debugging</strong>: Debugging a one-liner can be more challenging due to its compactness. Identifying issues or errors might take longer compared to well-structured, multiple-line code.</p>
</li>
<li><p><strong>Context</strong>: Not all situations warrant one-liners. Sometimes, a straightforward, explicit approach might be more suitable for code clarity, especially when working in teams.</p>
</li>
</ol>
<p>Ultimately, the decision to use one-liners should consider the trade-offs between conciseness and readability. Strive for a balance that enhances code clarity without compromising maintainability and understanding, especially when collaborating or working on larger projects.</p>
<h2 id="heading-wrapping-up"><strong>Wrapping Up</strong></h2>
<p>Mastering Python's concise techniques like list comprehensions, lambda functions, <code>enumerate</code>, <code>join</code>, <code>zip</code>, and unpacking with the <code>*</code> operator can significantly enhance code readability, efficiency, and simplicity. These methods offer elegant solutions to common programming challenges, reducing verbosity and improving code maintainability.</p>
<p>Understanding when and how to use these Pythonic constructs empowers developers to write cleaner, more expressive code and enhance overall productivity in various programming scenarios.</p>
]]></content:encoded></item><item><title><![CDATA[How To Send Emails Using Python?]]></title><description><![CDATA[Sending emails manually is time-consuming and error-prone, but it’s easy to automate with Python. Imagine a scenario where you can effortlessly send hundreds of customized emails to your customers, automate routine follow-ups, or send birthday wishes...]]></description><link>https://blog.ashutoshkrris.in/how-to-send-emails-using-python</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-send-emails-using-python</guid><category><![CDATA[Python]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Wed, 18 Oct 2023 12:50:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697633374557/1cfd4c37-7d77-4096-bb33-4daeadc5fcee.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sending emails manually is time-consuming and error-prone, but it’s easy to automate with Python. Imagine a scenario where you can effortlessly send hundreds of customized emails to your customers, automate routine follow-ups, or send birthday wishes automatically, all with the simplicity and elegance of Python code.</p>
<p>In this article, we're going to explore how Python can make your email life more effortless. I'll show you step-by-step how to get started and send plain-text and fancy emails (with attachments too!). All you need is Python installed on your system.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>Python comes with a built-in module called <code>smtplib</code> to send emails. It works by following a set of rules called the Simple Mail Transfer Protocol, or SMTP for short. Think of it like a recipe for sending emails. The <code>smtplib</code> module uses the <a target="_blank" href="https://tools.ietf.org/html/rfc821">RFC 821</a> protocol for SMTP.</p>
<p>For our examples, we will use Gmail's SMTP server for sending emails. In the next section, we will set up our Gmail account for sending out emails programmatically.</p>
<h3 id="heading-setting-up-gmail-for-sending-emails">Setting up Gmail for Sending Emails</h3>
<p>Though you can use your personal account to send emails, it's recommended to use a throw-away account for the tutorial. If you're ready with the Gmail account, follow the below steps to get started:</p>
<ol>
<li><p>Go to your Google Account Settings.</p>
</li>
<li><p>Choose "Security" and click on "2-Step Verification."</p>
</li>
<li><p>Scroll down to find "App passwords" and select it.</p>
</li>
<li><p>Give the password a name for reference. and click "Generate."</p>
</li>
<li><p>Follow the on-screen instructions and get the 16-character app password.</p>
</li>
<li><p>Click "Done."</p>
</li>
</ol>
<p>Make sure you copy and store the password somewhere safely as you won't be able to see it later.</p>
<h2 id="heading-how-to-secure-your-email-connections">How To Secure Your Email Connections?</h2>
<p>When you're sending emails with Python, it's crucial to keep your messages and login details safe from prying eyes. To do this, you can use encryption to protect your communication. Two common methods for encrypting your email connection are <strong>SSL (Secure Sockets Layer)</strong> and <strong>TLS (Transport Layer Security)</strong>.</p>
<p>To establish a secure connection with your email server, you have two options:</p>
<h3 id="heading-using-smtpssl">Using <code>SMTP_SSL()</code></h3>
<p>This method creates a secure connection right from the start, ensuring your communication is encrypted. The default port for this is 465. Thus, if <code>port</code> is zero, or not specified, <code>.SMTP_SSL()</code> will use this standard port for SMTP over SSL.</p>
<p>The following Python code example demonstrates this approach:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> smtplib
<span class="hljs-keyword">import</span> ssl
<span class="hljs-keyword">import</span> os

EMAIL = os.environ.get(<span class="hljs-string">"EMAIL"</span>)
PASSWORD = os.environ.get(<span class="hljs-string">"PASSWORD"</span>)
PORT = <span class="hljs-number">465</span>

context = ssl.create_default_context()

<span class="hljs-keyword">with</span> smtplib.SMTP_SSL(<span class="hljs-string">"smtp.gmail.com"</span>, PORT, context=context) <span class="hljs-keyword">as</span> server:
    server.login(EMAIL, PASSWORD)
    <span class="hljs-comment"># <span class="hljs-doctag">TODO:</span> Send email here</span>
</code></pre>
<p>In the above code, we retrieve the email and password from environment variables, which is a recommended practice for security. It then creates a secure SSL context using <code>ssl.create_default_context()</code>. The <code>with</code> statement sets up the secure connection to the Gmail SMTP server, using the provided server address and port, along with the SSL context to ensure a safe and encrypted connection. Once connected, the script logs in to the email server using the retrieved credentials. Using the <a target="_blank" href="https://earthly.dev/blog/use-with-keyword-in-py/"><code>with</code> context manager</a> ensures that the connection is closed properly when you're done.</p>
<h3 id="heading-using-starttls">Using <code>.starttls()</code></h3>
<p>This method first establishes an unsecured SMTP connection, and later encrypts using <code>.starttls()</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> smtplib
<span class="hljs-keyword">import</span> ssl

SMTP_SERVER = <span class="hljs-string">"smtp.gmail.com"</span>
PORT = <span class="hljs-number">587</span>
EMAIL = os.environ.get(<span class="hljs-string">"EMAIL"</span>)
PASSWORD = os.environ.get(<span class="hljs-string">"PASSWORD"</span>)

context = ssl.create_default_context()

<span class="hljs-keyword">with</span> smtplib.SMTP(SMTP_SERVER, PORT) <span class="hljs-keyword">as</span> server:
    server.ehlo()
    server.starttls(context=context)  <span class="hljs-comment"># Secure the connection</span>
    server.ehlo()
    server.login(EMAIL, PASSWORD)
    <span class="hljs-comment"># <span class="hljs-doctag">TODO:</span> Send an email here</span>
</code></pre>
<p>Within the <code>with</code> statement, the script initializes the connection to the SMTP server, introduces itself with <code>server.ehlo()</code>, secures the connection with <code>server.starttls(context=context)</code> for encryption, and logs in using the provided email and password.</p>
<p>You don't need to use <code>.helo()</code>(for SMTP) or <code>.ehlo()</code>(for ESMTP) explicitly because they are automatically called by <code>.starttls()</code> and <code>.sendmail()</code> if required. These functions handle the SMTP service extensions of the server, so you can generally omit using <code>.helo()</code> or <code>.ehlo()</code> unless you specifically need to check those extensions.</p>
<blockquote>
<p>Note: The above snippets use environment variables to store the email and password securely. You can create a <code>.env</code> file and set the values of <code>EMAIL</code> and <code>PASSWORD</code>. Then, you need to run <code>source .env</code> on your terminal to load these values. You can read more about them <a target="_blank" href="https://medium.com/p/201f4abd46b8">here</a>.</p>
</blockquote>
<h2 id="heading-how-to-send-plain-text-emails">How To Send Plain-Text Emails?</h2>
<p>Now that you've learned how to secure your SMTP connection, you're all set to send your first email using Python. Please note that we'll use <code>.starttls()</code> to encrypt the connection in the examples that follow.</p>
<p>To send an email, Python provides the <code>sendmail()</code> function, which does exactly what its name suggests: it sends an email. Here's the syntax of the <code>sendmail()</code> function:</p>
<pre><code class="lang-python">sendmail(sender_email, receiver_email, message)
</code></pre>
<ul>
<li><p><code>sender_email</code>: The email address of the sender.</p>
</li>
<li><p><code>receiver_email</code>: The email address of the recipient.</p>
</li>
<li><p><code>message</code>: The email content you want to send.</p>
</li>
</ul>
<p>Now, let's send our very first email:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> smtplib
<span class="hljs-keyword">import</span> ssl

SMTP_SERVER = <span class="hljs-string">"smtp.gmail.com"</span>
PORT = <span class="hljs-number">587</span>
EMAIL = os.environ.get(<span class="hljs-string">"EMAIL"</span>)
PASSWORD = os.environ.get(<span class="hljs-string">"PASSWORD"</span>)

context = ssl.create_default_context()

<span class="hljs-keyword">with</span> smtplib.SMTP(SMTP_SERVER, PORT) <span class="hljs-keyword">as</span> server:
    server.starttls(context=context)
    server.login(EMAIL, PASSWORD)
    message = <span class="hljs-string">"""\
    Subject: My First Email

    Hello there, this is my first email sent using Python.
    """</span>
    server.sendmail(EMAIL, <span class="hljs-string">"sogiho2398@weirby.com"</span>, message)
</code></pre>
<p>The <code>message</code> variable holds the content of the email, including the subject and the body of the message. The message starts with "Subject: My First Email" followed by two newlines(<code>\n</code>). This ensures <code>My First Email</code> shows up as the subject of the email, and the text following the newlines will be treated as the message body.</p>
<p>Then the <code>server.sendmail()</code> function is used to send the email from the sender's address to the recipient's address ("<a target="_blank" href="mailto:sogiho2398@weirby.com">sogiho2398@weirby.com</a>" in this case), along with the message content.</p>
<h2 id="heading-how-to-send-fancy-emails">How To Send Fancy Emails?</h2>
<p>In the previous section, you learned how you can send plain-text emails using Python. But, you won't always want to send those boring emails, right? Using Python, you can send emails with attachments as well as HTML content(yes, those fancy emails that have filled your inbox).</p>
<p>The built-in <code>email</code> package in Python enables you to create more fancy emails, which can be subsequently sent using the <code>smtplib</code> module, as you've already seen. In the following sections, you'll learn how to utilize the <code>email</code> package to send emails with HTML content and attachments, adding an extra layer of versatility to your email-sending capabilities.</p>
<h3 id="heading-multipurpose-internet-mail-extensions-mime">Multipurpose Internet Mail Extensions (MIME)</h3>
<p>The most common type of email we use today is called MIME (Multipurpose Internet Mail Extensions) Multipart email. It's like an email that can have different parts, like both regular text and fancy HTML. Python has a special module called <code>email.mime</code> that helps us create these kinds of emails. With it, we can make emails that look nice, have plain text, and even attach things like pictures or documents. This is how we send cool newsletters, attachments, or emails with both simple text and pretty pictures. It's a crucial tool for making emails more interesting and useful. If you need more information on how to use it, you can find detailed instructions in <a target="_blank" href="https://docs.python.org/3/library/email.mime.html">the official documentation</a>.</p>
<h3 id="heading-including-attachments">Including Attachments</h3>
<p>In this section, we'll explore how to send emails with attachments using Python. Sending emails with attachments can be incredibly useful, especially when you need to share files or documents. We'll use the <code>email</code> and <code>smtplib</code> modules to accomplish this.</p>
<p>The following code shows how you can send an email with an image attachment:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> smtplib
<span class="hljs-keyword">import</span> ssl

<span class="hljs-keyword">from</span> email <span class="hljs-keyword">import</span> encoders
<span class="hljs-keyword">from</span> email.mime.base <span class="hljs-keyword">import</span> MIMEBase
<span class="hljs-keyword">from</span> email.mime.multipart <span class="hljs-keyword">import</span> MIMEMultipart
<span class="hljs-keyword">from</span> email.mime.text <span class="hljs-keyword">import</span> MIMEText

SMTP_SERVER = <span class="hljs-string">"smtp.gmail.com"</span>
PORT = <span class="hljs-number">587</span>
EMAIL = os.environ.get(<span class="hljs-string">"EMAIL"</span>)
PASSWORD = os.environ.get(<span class="hljs-string">"PASSWORD"</span>)

subject = <span class="hljs-string">"My Second Email"</span>
body = <span class="hljs-string">"Hello there, I hope you are able to see my attached image."</span>
receiver_email = <span class="hljs-string">"sogiho2398@weirby.com"</span>

message = MIMEMultipart()
message[<span class="hljs-string">"From"</span>] = EMAIL
message[<span class="hljs-string">"To"</span>] = receiver_email
message[<span class="hljs-string">"Subject"</span>] = subject

message.attach(MIMEText(body, <span class="hljs-string">"plain"</span>))

filename = <span class="hljs-string">"image.png"</span>

<span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">"rb"</span>) <span class="hljs-keyword">as</span> attachment:
    part = MIMEBase(<span class="hljs-string">"application"</span>, <span class="hljs-string">"octet-stream"</span>)
    part.set_payload(attachment.read())

encoders.encode_base64(part)

part.add_header(
    <span class="hljs-string">"Content-Disposition"</span>,
    <span class="hljs-string">f"attachment; filename= <span class="hljs-subst">{filename}</span>"</span>,
)

message.attach(part)
text = message.as_string()

context = ssl.create_default_context()
<span class="hljs-keyword">with</span> smtplib.SMTP_SSL(SMTP_SERVER, PORT, context=context) <span class="hljs-keyword">as</span> server:
    server.login(EMAIL, PASSWORD)
    server.sendmail(EMAIL, receiver_email, text)
</code></pre>
<p>The above code uses the <code>MIMEMultipart</code> class to structure the email, providing fields for sender, recipient, and subject. The email's body is added using MIMEText. To attach a file, it selects the file ("image.png" in this case), encodes it using base64 encoding, and attaches it to the email. This step allows you to include files like images, documents, or any binary data. The email message is then converted to a string for transmission.</p>
<p>Here's how you email should look:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697630883172/34ce4317-a8d7-47e0-9aec-f75326dc874e.png" alt="Email with Attachment" class="image--center mx-auto" /></p>
<h3 id="heading-including-html-content">Including HTML Content</h3>
<p>HTML emails are a powerful way to create visually appealing messages with various formatting and styling options. You can define the HTML content in the same Python file or in a different HTML file itself. But it would be ideal to separate it from your Python code, else the code will grow longer.</p>
<p>Here's the code that demonstrates how to send HTML emails:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> smtplib
<span class="hljs-keyword">import</span> ssl

<span class="hljs-keyword">from</span> email.mime.multipart <span class="hljs-keyword">import</span> MIMEMultipart
<span class="hljs-keyword">from</span> email.mime.text <span class="hljs-keyword">import</span> MIMEText

SMTP_SERVER = <span class="hljs-string">"smtp.gmail.com"</span>
PORT = <span class="hljs-number">587</span>
EMAIL = os.environ.get(<span class="hljs-string">"EMAIL"</span>)
PASSWORD = os.environ.get(<span class="hljs-string">"PASSWORD"</span>)

subject = <span class="hljs-string">"My Third Email"</span>
receiver_email = <span class="hljs-string">"sogiho2398@weirby.com"</span>

message = MIMEMultipart(<span class="hljs-string">"alternative"</span>)
message[<span class="hljs-string">"From"</span>] = EMAIL
message[<span class="hljs-string">"To"</span>] = receiver_email
message[<span class="hljs-string">"Subject"</span>] = subject

filename = <span class="hljs-string">"email.html"</span>

text = <span class="hljs-string">"""\
Hi there,

Sometimes you just want to send a simple HTML email with a simple design and clear call to action. This is it.

This is a really simple email template. Its sole purpose is to get the recipient to click the button with no distractions.

Good luck! Hope it works.
"""</span>

<span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    html = file.read()

part1 = MIMEText(text, <span class="hljs-string">"plain"</span>)
part2 = MIMEText(html, <span class="hljs-string">"html"</span>)

message.attach(part1)
message.attach(part2)

text = message.as_string()

context = ssl.create_default_context()
<span class="hljs-keyword">with</span> smtplib.SMTP(SMTP_SERVER, PORT) <span class="hljs-keyword">as</span> server:
    server.starttls(context=context)
    server.login(EMAIL, PASSWORD)
    server.sendmail(EMAIL, receiver_email, text)
</code></pre>
<p>To structure the email, we use <code>MIMEMultipart("alternative")</code>, enabling the inclusion of both plain text and HTML content. We read the HTML content from a file "email.html". You can get the contents of this HTML file from <a target="_blank" href="https://github.com/leemunroe/responsive-html-email-template/blob/master/email.html">here</a>. We also create two parts - one for plaintext and one for HTML. This is required as not all email clients display HTML content by default. The message is finally converted into text and the email is sent.</p>
<p>Here's how your HTML email looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1697631404514/4ea7bea2-8161-4f31-a40c-9e67d9ff9e86.png" alt="HTML Email" class="image--center mx-auto" /></p>
<h2 id="heading-how-to-send-bulk-emails">How To Send Bulk Emails?</h2>
<p>In many real-world scenarios, sending a single email is not sufficient. Whether you're managing a mailing list, delivering regular updates to subscribers, or sending notifications to a large number of recipients, there comes a time when you need to send multiple emails efficiently. In this section, we will learn how to read a CSV file and send them personalized emails.</p>
<p>Let's start with creating a CSV file called "receivers.csv" and add the following content:</p>
<pre><code class="lang-plaintext">name,email,designation,salary
Person 1,sogiho2398@weirby.com,Application Developer I,20000 USD
Person 2,sogiho2398@weirby.com,Application Developer II,30000 USD 
Person 3,sogiho2398@weirby.com,Application Developer III,50000 USD
Person 4,sogiho2398@weirby.com,Application Developer IV,80000 USD
</code></pre>
<p>Make sure you separate the values with commas(,).</p>
<p>Next, let's read this file and iterate over the values:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> csv


<span class="hljs-keyword">with</span> open(<span class="hljs-string">"receivers.csv"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    reader = csv.reader(file)
    next(reader)
    <span class="hljs-keyword">for</span> name, email, designation, salary <span class="hljs-keyword">in</span> reader:
        print(<span class="hljs-string">f"Sending email to <span class="hljs-subst">{name}</span> on email: <span class="hljs-subst">{email}</span>"</span>)
        <span class="hljs-comment"># <span class="hljs-doctag">TODO:</span> Send email</span>
</code></pre>
<p>The above code reads the "receivers.csv" file and iterates over the CSV data. It skips the header row using <code>next(reader)</code>. For each subsequent row, it extracts the name, email, designation, and salary.</p>
<p>Let us now send the emails to the users:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> csv
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> smtplib
<span class="hljs-keyword">import</span> ssl

SMTP_SERVER = <span class="hljs-string">"smtp.gmail.com"</span>
PORT = <span class="hljs-number">587</span>
EMAIL = os.environ.get(<span class="hljs-string">"EMAIL"</span>)
PASSWORD = os.environ.get(<span class="hljs-string">"PASSWORD"</span>)

context = ssl.create_default_context()

<span class="hljs-keyword">with</span> smtplib.SMTP(SMTP_SERVER, PORT) <span class="hljs-keyword">as</span> server:
    server.starttls(context=context)
    server.login(EMAIL, PASSWORD)

    <span class="hljs-keyword">with</span> open(<span class="hljs-string">"receivers.csv"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
        reader = csv.reader(file)
        next(reader)
        <span class="hljs-keyword">for</span> name, email, designation, salary <span class="hljs-keyword">in</span> reader:
            message = <span class="hljs-string">f"""\
            Subject: <span class="hljs-subst">{name}</span>, you're hired!

            Hi <span class="hljs-subst">{name}</span>

            Congratulations, you're hired for the role of <span class="hljs-subst">{designation}</span>. Your salary will be <span class="hljs-subst">{salary}</span>.

            Thanks
            HR    
            """</span>
            server.sendmail(EMAIL, email, message)
</code></pre>
<p>In each iteration, we construct the personalized message using <code>f-strings</code> and send the message to the respective users.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we've explored how Python can be used to send emails in different ways. We've learned how to make email connections secure, send emails with fancy designs or attachments, and even send emails to many people at once.</p>
<p>Python's tools make it easy to send various types of emails, whether for personal use or in a professional setting. This can save time and make your messages more engaging. In a world where email is a crucial part of our daily lives, Python offers you the ability to send emails efficiently and effectively, no matter your background or needs.</p>
]]></content:encoded></item><item><title><![CDATA[How To Generate OTPs Using PyOTP in Python]]></title><description><![CDATA[In a digital age filled with hackers and cybersecurity threats where "password123" just doesn't cut it anymore, Two-Factor Authentication (2FA) emerges as the superhero of online security. OTPs are an important part of 2FA. In this article, we'll lea...]]></description><link>https://blog.ashutoshkrris.in/how-to-generate-otps-using-pyotp-in-python</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-generate-otps-using-pyotp-in-python</guid><category><![CDATA[Python]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Security]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sun, 01 Oct 2023 07:19:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1696144698813/b5dc7bf6-825b-46f6-aa2a-f1cda218bfe2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In a digital age filled with hackers and cybersecurity threats where "password123" just doesn't cut it anymore, Two-Factor Authentication (2FA) emerges as the superhero of online security. OTPs are an important part of 2FA. In this article, we'll learn how to create OTPs using Python and the PyOTP library. So, grab your Python wizard hat, and let's dive in!</p>
<h2 id="heading-what-are-otps">What are OTPs?</h2>
<p>You're no stranger to the scenario: you're online, making that critical purchase, and then it happens - the dreaded login screen. Before you use your trusty "password123," you should know it's not as strong as you think. But don't worry, we've got a superhero in the digital world - OTPs!</p>
<p><a target="_blank" href="https://www.freepik.com/free-vector/enter-otp-concept-illustration_20602807.htm#query=otp&amp;position=0&amp;from_view=keyword&amp;track=sph"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696164298514/31ce8e39-1ee7-47e4-8924-c7011fd8cfa2.jpeg" alt="Image by storyset on Freepik" class="image--center mx-auto" /></a></p>
<p>An OTP, or One-Time Password, is a temporary code that changes each time you use it. It's like having a new secret handshake every time you want to access your online accounts. This dynamic nature makes OTPs incredibly secure, as they're almost impossible for malicious actors to predict or crack.</p>
<p>Before we dive into the code, let's understand the two main types of OTPs:</p>
<p><strong>1. Time-based OTP (TOTP):</strong> These OTPs change at regular time intervals (usually 30 or 60 seconds). Think of it as a constantly evolving secret code that only you and your device know.</p>
<p><strong>2. HMAC-based OTP (HOTP):</strong> In contrast, HOTPs are event-based OTPs. They change each time you authenticate, providing an extra layer of security.</p>
<h2 id="heading-how-to-generate-otps-using-python">How To Generate OTPs Using Python?</h2>
<p>In Python, you can generate OTPs using the <code>random</code> library as below:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> choice
<span class="hljs-keyword">import</span> string


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_otp</span>(<span class="hljs-params">number_of_digits</span>):</span>
    otp = <span class="hljs-string">''</span>.join(choice(string.digits) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(number_of_digits))
    <span class="hljs-keyword">return</span> otp


print(generate_otp(<span class="hljs-number">6</span>))
</code></pre>
<p>The above <code>generate_otp</code> method uses list comprehension to generate an OTP of the required number of digits. However, there are a few limitations to generating OTPs this way. The generated OTPs are predictable and attackers can easily predict the values. These OTPs do not have a built-in expiration time. For security reasons, OTPs should have a limited validity period to prevent replay attacks. The <code>random</code> module is not intended for cryptographic purposes. For high-security applications, it's better to use a cryptographic library like <code>secrets</code> or dedicated OTP generation libraries that provide cryptographically secure randomness.</p>
<p>This is where libraries such as <code>PytOTP</code> come into the picture. <a target="_blank" href="https://pyauth.github.io/pyotp/#">PyOTP</a> is a fantastic Python library that simplifies the creation and verification of OTPs. With PyOTP, you can generate OTPs using Time-based OTP (TOTP) and HMAC-based OTP (HOTP) algorithms effortlessly. So, let's get started!</p>
<h2 id="heading-how-to-generate-otps-using-pyotp">How to Generate OTPs using PyOTP?</h2>
<p>Before you can start generating OTPs, you need to install PyOTP. If you don't have Python installed, go ahead and do that first. Then, open your terminal and run the following command:</p>
<pre><code class="lang-bash">pip install pyotp
</code></pre>
<p>This command installs PyOTP and prepares you for the exciting journey ahead. Please note that you can also create a virtual environment before installing PyOTP. But for the sake of this simple tutorial, we won't be doing that here.</p>
<h3 id="heading-time-based-otps-totps">Time-Based OTPs (TOTPs)</h3>
<p>The <strong>moving factor in a TOTP is time-based</strong>. The amount of time duration for which the OTP is valid is called <strong>timestep</strong>. If you haven’t used your password within the timestep window, it will no longer be valid, and you’ll need to request a new one.</p>
<p>Let's start by importing the PyOTP library. We'll also create a secret key using the PyOTP library. Remember, this key should be kept as secret as your mother's secret recipe for your favorite food!</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)</span>
secret_key = pyotp.random_base32()
</code></pre>
<p>PyOTP provides a <code>random_base32()</code> function that helps you generate a random secret key in Base32 encoding. It generates a random sequence of bytes, which is essentially a random collection of numbers and letters. It then encodes this random sequence of bytes into Base32 format.</p>
<p>Now, let's generate an OTP using our secret key. We'll use the TOTP algorithm:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Generate an OTP using TOTP</span>
otp = pyotp.TOTP(secret_key)
otp_code = otp.now()

print(<span class="hljs-string">"Your Time-based OTP:"</span>, otp_code)
</code></pre>
<p>That's it! You've just created a Time-based OTP. This code will generate a new OTP every 30 seconds, making it an excellent choice for securing your online accounts.</p>
<pre><code class="lang-bash">Your Time-based OTP: 641079
</code></pre>
<p>Do you want to verify that the OTP changes after 30 seconds? Let's use the <code>sleep</code> function:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)̥</span>
secret_key = pyotp.random_base32()

otp = pyotp.TOTP(secret_key)
<span class="hljs-comment"># Generate an OTP using TOTP after every 30 seconds</span>
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    print(<span class="hljs-string">f"Your Time-based OTP at <span class="hljs-subst">{time.ctime()}</span>:"</span>, otp.now())

    time.sleep(<span class="hljs-number">30</span>)
</code></pre>
<p>In the above code, you enter an infinite loop (<code>while True</code>) to continuously generate OTPs. Inside the loop, you generate a TOTP and then let the code sleep for 30 seconds. Then after 30 seconds, it again generates the OTP. You will see an output as below:</p>
<pre><code class="lang-bash">Your Time-based OTP at Sun Oct  1 11:42:06 2023: 127722
Your Time-based OTP at Sun Oct  1 11:42:36 2023: 582057
Your Time-based OTP at Sun Oct  1 11:43:06 2023: 744459
Your Time-based OTP at Sun Oct  1 11:43:36 2023: 508890
</code></pre>
<h3 id="heading-hmac-based-otps-hotps"><strong>HMAC-based OTPs (HOTPs)</strong></h3>
<p>HOTPs are <strong>event-based OTPs where the moving factor in each code is based on a counter</strong>. Each time the HOTP is requested and validated, the moving factor is incremented based on a counter.</p>
<p>While Time-based OTPs are fantastic, HMAC-based OTPs offer another layer of security. Let's take a look at generating HOTPs.</p>
<p>Start by importing the library and generating the secret key.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)̥</span>
secret_key = pyotp.random_base32()
</code></pre>
<p>Next, you can generate the OTP as below:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)̥</span>
secret_key = pyotp.random_base32()

<span class="hljs-comment"># Generate an OTP using HOTP</span>
hotp = pyotp.HOTP(secret_key)
otp_code = hotp.at(<span class="hljs-number">0</span>)  <span class="hljs-comment"># You can use different counter values for different OTPs</span>

print(<span class="hljs-string">"Your HMAC-based OTP:"</span>, otp_code)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Your HMAC-based OTP: 469785
</code></pre>
<p>With this code, you'll have a new HMAC-based OTP each time you increment the counter value.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)̥</span>
secret_key = pyotp.random_base32()

<span class="hljs-comment"># Generate an OTP using HOTP</span>
hotp = pyotp.HOTP(secret_key)

print(<span class="hljs-string">"Your HMAC-based OTP at counter 0:"</span>, hotp.at(<span class="hljs-number">0</span>))
print(<span class="hljs-string">"Your HMAC-based OTP at counter 1:"</span>, hotp.at(<span class="hljs-number">1</span>))
print(<span class="hljs-string">"Your HMAC-based OTP at counter 2:"</span>, hotp.at(<span class="hljs-number">2</span>))
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Your HMAC-based OTP at counter 0: 230227
Your HMAC-based OTP at counter 1: 437103
Your HMAC-based OTP at counter 2: 290927
</code></pre>
<h2 id="heading-how-to-customize-the-otp-generation"><strong>How to Customize the OTP Generation?</strong></h2>
<p>Just as you order pizza with customizations like extra cheese and toppings, you can customize the OTPs when generating using PyOTP. You can adjust the length, choose different algorithms, and set expiration periods to suit your needs. These customizations are possible for both the <code>TOTP</code> and <code>HOTP</code> classes.</p>
<p>Let's explore some customization options:</p>
<h3 id="heading-adjusting-otp-length">Adjusting OTP Length</h3>
<p>By default, PyOTP generates OTPs with 6 digits. However, you can easily customize the length of your OTPs. For example, if you want to generate OTPs with 4 digits, you can do so as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)</span>
secret_key = pyotp.random_base32()

<span class="hljs-comment"># Create a TOTP object with a custom OTP length (e.g., 4 digits)</span>
otp = pyotp.TOTP(secret_key, digits=<span class="hljs-number">4</span>)

<span class="hljs-comment"># Generate and print the OTP</span>
print(<span class="hljs-string">"You 4-Digit OTP:"</span>, otp.now())
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">You 4-Digit OTP: 9854
</code></pre>
<p>By setting the <code>digits</code> parameter to 4, you've changed the OTP length for this TOTP object to 4 digits instead of the default 6 digits.</p>
<h3 id="heading-handling-otp-expiration"><strong>Handling OTP Expiration</strong></h3>
<p>Sometimes, you might want to set an expiration period for your OTPs. You can do this by specifying the <code>interval</code> parameter when creating a TOTP object. For example, if you want OTPs to expire every 60 seconds, you can configure it like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)</span>
secret_key = pyotp.random_base32()

<span class="hljs-comment"># Create a TOTP object with a custom expiration interval (60 seconds)</span>
otp = pyotp.TOTP(secret_key, interval=<span class="hljs-number">60</span>)

<span class="hljs-comment"># Generate and print the OTP</span>
print(<span class="hljs-string">"OTP with 60-second expiration:"</span>, otp.now())
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">OTP with 60-second expiration: 144980
</code></pre>
<p>To verify this, you can set your code to sleep for 30 seconds, and see that the same OTP is printed twice in a minute:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)̥</span>
secret_key = pyotp.random_base32()


otp = pyotp.TOTP(secret_key, interval=<span class="hljs-number">60</span>)
<span class="hljs-comment"># Generate an OTP using TOTP after every 60 seconds</span>
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
    print(<span class="hljs-string">f"Your Time-based OTP at <span class="hljs-subst">{time.ctime()}</span>:"</span>, otp.now())

    time.sleep(<span class="hljs-number">30</span>)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Your Time-based OTP at Sun Oct  1 12:22:11 2023: 043977
Your Time-based OTP at Sun Oct  1 12:22:41 2023: 043977
Your Time-based OTP at Sun Oct  1 12:23:11 2023: 491773
Your Time-based OTP at Sun Oct  1 12:23:41 2023: 491773
Your Time-based OTP at Sun Oct  1 12:24:11 2023: 468957
</code></pre>
<p>There are more customizations available but they are out of scope for this tutorial. By customizing OTP generation in these ways, you can tailor your OTPs to fit your application's security requirements and user experience.</p>
<h2 id="heading-how-to-verify-the-otps">How to Verify the OTPs?</h2>
<p>Creating OTPs is just one side of the coin; verifying them is equally important. PyOTP simplifies OTP verification through its <code>verify</code> method. Let's explore how to verify OTPs using PyOTP.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pyotp

<span class="hljs-comment"># Create a secret key (keep it secret!)̥</span>
secret_key = pyotp.random_base32()

otp = pyotp.TOTP(secret_key, interval=<span class="hljs-number">60</span>)
<span class="hljs-comment"># Generate an OTP using TOTP after every 30 seconds</span>
print(<span class="hljs-string">"Your TOTP is: "</span>, otp.now())

user_otp = input(<span class="hljs-string">"Enter the OTP: "</span>)
<span class="hljs-keyword">if</span> (otp.verify(user_otp)):
    print(<span class="hljs-string">"Access granted!"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"Incorrect OTP"</span>)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Your TOTP is:  747559
Enter the OTP: 747559
Access granted!
</code></pre>
<pre><code class="lang-bash">Your TOTP is:  676707
Enter the OTP: 123456
Incorrect OTP
</code></pre>
<p>By using the <code>verify</code> method, you can easily determine whether the user-provided OTP matches the expected OTP generated from the secret key. If they match, access is granted; otherwise, access is denied.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Now that you've got your OTP-generating skills down, you can integrate OTPs into your Python applications. In a world where "password123" just won't cut it anymore, OTPs are your digital knights in shining armor. PyOTP, with its Pythonic charm, makes implementing OTPs a breeze. So, go ahead, give it a try, and keep those cyber villains at bay.</p>
]]></content:encoded></item><item><title><![CDATA[How To Implement a Referral System in Your Medusa Store]]></title><description><![CDATA[Referral systems are a powerful marketing tool that leverage existing customers to promote a product or service to their network. Businesses can tap into their loyal customer base by rewarding customers to refer others and expand their reach organica...]]></description><link>https://blog.ashutoshkrris.in/how-to-implement-a-referral-system-in-your-medusa-store</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-implement-a-referral-system-in-your-medusa-store</guid><category><![CDATA[medusa]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[ecommerce]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sun, 11 Jun 2023 11:17:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1686481909133/22e809b9-f874-4798-b307-f3853298bad2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Referral systems are a powerful marketing tool that leverage existing customers to promote a product or service to their network. Businesses can tap into their loyal customer base by rewarding customers to refer others and expand their reach organically.</p>
<p>In this tutorial, you will explore how to implement a referral system in your Medusa e-commerce store. By implementing this feature, your customers will have the ability to refer other users and receive discounts on their future purchases. Additionally, the referred customers will also be eligible for a discount when they use a referral code during the sign-up process.</p>
<p>Here is a quick demo of what you're going to build in this tutorial:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/zuur8gU-DX4">https://youtu.be/zuur8gU-DX4</a></div>
<p> </p>
<p>You can find the code for the tutorial in <a target="_blank" href="https://github.com/ashutoshkrris/medusa-referral-system">this repository</a>.</p>
<h2 id="heading-what-is-medusa">What is Medusa?</h2>
<p>Medusa is an open source, composable commerce platform designed for developers. With its flexible architecture, Medusa enables users to create custom commerce solutions that meet their specific needs. It provides modular commerce infrastructure that makes custom development processes easier for developers. Medusa leverages cutting-edge infrastructure technologies such as serverless and edge workers to ensure scalability, reliability, and performance.</p>
<p><img src="https://res.cloudinary.com/dza7lstvk/image/upload/fl_lossy/f_auto/r_16/ar_16:9,c_pad/v1/Medusa%20Docs/Diagrams/medusa-architecture-3_e385zk.jpg?_a=ATAPpAA0" alt="Medusa Architecture" class="image--center mx-auto" /></p>
<p>The highly extensible architecture enables developers to easily create custom features, such as automating customer group assignments and <a target="_blank" href="https://medusajs.com/blog/chatgpt-medusa/">integrating ChatGPT to automate writing product descriptions</a>. The concepts like <a target="_blank" href="https://docs.medusajs.com/advanced/backend/subscribers/overview/">Subscribers</a> and <a target="_blank" href="https://docs.medusajs.com/advanced/backend/events/architecture">Events architecture</a> in Medusa make it fairly simple to extend the store capabilities.</p>
<blockquote>
<p>Learn more about the architecture of Medusa in their <a target="_blank" href="https://docs.medusajs.com/development/fundamentals/architecture-overview">official documentation</a>.</p>
</blockquote>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you get started with the tutorial, you should have installed:</p>
<ul>
<li><p><a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment#nodejs">Node.js(V16 or later)</a></p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment/#git">Git</a></p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment#medusa-cli">Medusa CLI</a></p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment/#redis">Redis</a>: Used by Medusa to handle the event queue.</p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/development/backend/prepare-environment#postgresql">PostgreSQL</a></p>
</li>
</ul>
<h2 id="heading-setting-up-the-medusa-backend">Setting up the Medusa Backend</h2>
<p>The Medusa Backend serves as the central component responsible for the store's logic and data management. It exposes REST APIs that are utilized by the Medusa Admin and Storefront to perform operations like retrieving, creating, and modifying data.</p>
<p>In this section, you will go through setting up your Medusa backend. Follow these steps to create a new Medusa store named "my-medusa-store":</p>
<pre><code class="lang-bash">medusa new my-medusa-store
</code></pre>
<p>Open the <code>.env</code> file present in the <code>my-medusa-store</code> directory and add the database URL as below:</p>
<pre><code class="lang-bash">JWT_SECRET=something
COOKIE_SECRET=something

DATABASE_TYPE=<span class="hljs-string">"postgres"</span>
DATABASE_URL=<span class="hljs-string">"postgres://&lt;your-username&gt;:&lt;your-password&gt;@localhost:5432/&lt;your-database&gt;"</span>
REDIS_URL=redis://localhost:6379
</code></pre>
<blockquote>
<p>Note: Replace the <code>your-username</code>, <code>your-password</code> and <code>your-database</code> with your own values.</p>
</blockquote>
<p>Next, open the <code>medusa-config.js</code> file and uncomment the <code>redis_url</code> in the <code>projectConfig</code> object:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/** <span class="hljs-doctag">@type <span class="hljs-type">{import('@medusajs/medusa').ConfigModule["projectConfig"]}</span> </span>*/</span>
<span class="hljs-keyword">const</span> projectConfig = {
  <span class="hljs-attr">jwtSecret</span>: process.env.JWT_SECRET,
  <span class="hljs-attr">cookieSecret</span>: process.env.COOKIE_SECRET,
  <span class="hljs-attr">database_database</span>: <span class="hljs-string">"./medusa-db.sql"</span>,
  <span class="hljs-attr">database_type</span>: DATABASE_TYPE,
  <span class="hljs-attr">store_cors</span>: STORE_CORS,
  <span class="hljs-attr">admin_cors</span>: ADMIN_CORS,
  <span class="hljs-comment">// Uncomment the following lines to enable REDIS</span>
  <span class="hljs-attr">redis_url</span>: REDIS_URL
}
</code></pre>
<p>Now, run the migrations and seed the test data present in the <code>data/seed.json</code> file to the PostgreSQL database:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-medusa-store
medusa migrations run
medusa seed -f ./data/seed.json
</code></pre>
<p>Once the data is seeded, start the Medusa server by running this command:</p>
<pre><code class="lang-bash">medusa develop
</code></pre>
<p>These steps may take a few minutes to set up and run the server on port 9000. To test your server, you can either visit <a target="_blank" href="http://localhost:9000/store/products"><strong>http://localhost:9000/store/products</strong></a> in your browser or use the following command:</p>
<pre><code class="lang-bash">curl localhost:9000/store/products
</code></pre>
<p>If your server has been set up successfully, you will receive a response displaying a list of products and related details.</p>
<h2 id="heading-create-a-referral-entity">Create a Referral Entity</h2>
<p>The referral entity is an essential component of the referral system in Medusa. It represents a referral in the system and stores relevant information such as the referral code and the referrer customer. Let's explore why we need a referral entity and how to create it in the backend.</p>
<p>Start by creating a new <code>referral.ts</code> file in the <code>src/models</code> directory. This file will define the structure and behavior of your referral entity.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { BaseEntity } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>
<span class="hljs-keyword">import</span> { Customer } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa/dist/models"</span>
<span class="hljs-keyword">import</span> {
    Column,
    Entity,
    JoinColumn,
    OneToOne
} <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>

<span class="hljs-meta">@Entity</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Referral <span class="hljs-keyword">extends</span> BaseEntity {
    <span class="hljs-meta">@Column</span>({ <span class="hljs-keyword">type</span>: <span class="hljs-string">"varchar"</span> })
    referral_code: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>

    <span class="hljs-meta">@OneToOne</span>(<span class="hljs-function">() =&gt;</span> Customer)
    <span class="hljs-meta">@JoinColumn</span>({ name: <span class="hljs-string">"referrer_customer_id"</span> })
    referrer_customer: Customer
}
</code></pre>
<p>In the above code, the <code>Referral</code> entity class extends the <code>BaseEntity</code> provided by Medusa to automatically inherits additional columns such as <code>id</code>, <code>created_at</code>, and <code>updated_at</code>. In addition to that, the entity includes the following attributes:</p>
<ul>
<li><p><code>referral_code</code>: A string column that represents the referral code associated with the referral.</p>
</li>
<li><p><code>referrer_customer</code>: A one-to-one relationship with the <code>Customer</code> entity, representing the customer who referred others.</p>
</li>
</ul>
<p>Medusa uses a specific format for entity IDs, which is <code>&lt;PREFIX&gt;_&lt;RANDOM&gt;</code>. For example, a referral might have an ID like <code>referral_01G35WVGY4D1JCA4TPGVXPGCQM</code>.</p>
<p>To generate an ID for the <code>Referral</code> entity that matches the IDs generated for Medusa's core entities, you need to add a <code>BeforeInsert</code> event handler. Inside this handler, you can use the <code>generateEntityId</code> utility function provided by Medusa to generate the ID. The <code>generateEntityId</code> function takes the current ID as the first parameter and the desired prefix as the second parameter.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { BaseEntity } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>
<span class="hljs-keyword">import</span> { Customer } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa/dist/models"</span>
<span class="hljs-keyword">import</span> { generateEntityId } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa/dist/utils"</span>
<span class="hljs-keyword">import</span> {
    BeforeInsert,
    Column,
    Entity,
    JoinColumn,
    OneToOne
} <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>

<span class="hljs-meta">@Entity</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Referral <span class="hljs-keyword">extends</span> BaseEntity {
    <span class="hljs-meta">@Column</span>({ <span class="hljs-keyword">type</span>: <span class="hljs-string">"varchar"</span> })
    referral_code: <span class="hljs-built_in">string</span> | <span class="hljs-literal">null</span>

    <span class="hljs-meta">@OneToOne</span>(<span class="hljs-function">() =&gt;</span> Customer)
    <span class="hljs-meta">@JoinColumn</span>({ name: <span class="hljs-string">"referrer_customer_id"</span> })
    referrer_customer: Customer

    <span class="hljs-meta">@BeforeInsert</span>()
    <span class="hljs-keyword">private</span> beforeInsert(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">this</span>.id = generateEntityId(<span class="hljs-built_in">this</span>.id, <span class="hljs-string">"referral"</span>)
    }
}
</code></pre>
<h3 id="heading-create-a-migration">Create a Migration</h3>
<p>Since you created a new entity, you need to create a migration for your entity to update the database schema with the new table. To create a migration that makes changes to your Medusa schema, run the following command:</p>
<pre><code class="lang-bash">npx typeorm migration:create src/migrations/ReferralCreated
</code></pre>
<p>This will create the migration file in the specified path. The contents of the file looks like the below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { MigrationInterface, QueryRunner } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ReferralCreated1686235820432 <span class="hljs-keyword">implements</span> MigrationInterface {

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> up(queryRunner: QueryRunner): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt; {
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> down(queryRunner: QueryRunner): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt; {
    }
}
</code></pre>
<p>In the above code, the class implements the <code>MigrationInterface</code> from TypeORM, which requires the implementation of two methods: <code>up</code> and <code>down</code>. These methods define the actions to be performed when applying or reverting the migration, respectively.</p>
<p>Next, implement the <code>up</code> and <code>down</code> methods as below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { MigrationInterface, QueryRunner, Table, TableForeignKey } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ReferralCreated1686235820432 <span class="hljs-keyword">implements</span> MigrationInterface {

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> up(queryRunner: QueryRunner): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt; {
        <span class="hljs-keyword">await</span> queryRunner.createTable(
            <span class="hljs-keyword">new</span> Table({
                name: <span class="hljs-string">"referral"</span>,
                columns: [
                    {
                        name: <span class="hljs-string">"id"</span>,
                        <span class="hljs-keyword">type</span>: <span class="hljs-string">"varchar"</span>,
                        isPrimary: <span class="hljs-literal">true</span>,
                    },
                    {
                        name: <span class="hljs-string">"referral_code"</span>,
                        <span class="hljs-keyword">type</span>: <span class="hljs-string">"varchar"</span>,
                        isNullable: <span class="hljs-literal">true</span>,
                    },
                    {
                        name: <span class="hljs-string">"referrer_customer_id"</span>,
                        <span class="hljs-keyword">type</span>: <span class="hljs-string">"varchar"</span>,
                    },
                    {
                        name: <span class="hljs-string">"created_at"</span>,
                        <span class="hljs-keyword">type</span>: <span class="hljs-string">"timestamp"</span>,
                        <span class="hljs-keyword">default</span>: <span class="hljs-string">"now()"</span>,
                    },
                    {
                        name: <span class="hljs-string">"updated_at"</span>,
                        <span class="hljs-keyword">type</span>: <span class="hljs-string">"timestamp"</span>,
                        <span class="hljs-keyword">default</span>: <span class="hljs-string">"now()"</span>,
                    },
                ],
            })
        );

        <span class="hljs-keyword">await</span> queryRunner.createForeignKey(
            <span class="hljs-string">"referral"</span>,
            <span class="hljs-keyword">new</span> TableForeignKey({
                columnNames: [<span class="hljs-string">"referrer_customer_id"</span>],
                referencedColumnNames: [<span class="hljs-string">"id"</span>],
                referencedTableName: <span class="hljs-string">"customer"</span>,
                onDelete: <span class="hljs-string">"CASCADE"</span>,
            })
        );
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> down(queryRunner: QueryRunner): <span class="hljs-built_in">Promise</span>&lt;<span class="hljs-built_in">void</span>&gt; {
        <span class="hljs-keyword">await</span> queryRunner.dropTable(<span class="hljs-string">"referral"</span>);
    }

}
</code></pre>
<p>The <code>up</code> method performs two operations - create a new <code>referral</code> table with the defined columns and create the foreign key constraint on the <code>referrer_customer_id</code> column, referencing the <code>id</code> column of the <code>customer</code> table. The <code>down</code> method simply drops the <code>referral</code> table.</p>
<h3 id="heading-create-a-repository">Create a Repository</h3>
<p>To conveniently access and modify data related to the Referral entity, you can create a TypeORM repository. Create a file named <code>referral.ts</code> in the <code>src/repositories</code> directory and add the following code to the file:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { dataSource } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa/dist/loaders/database"</span>;
<span class="hljs-keyword">import</span> { Referral } <span class="hljs-keyword">from</span> <span class="hljs-string">"../models/referral"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ReferralRepository = dataSource
    .getRepository(Referral);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferralRepository;
</code></pre>
<p>The <code>ReferralRepository</code> is created using the <code>getRepository</code> method provided by the <code>dataSource</code> exported from the core package in Medusa.</p>
<h3 id="heading-run-migrations">Run Migrations</h3>
<p>Before you start using your entity, make sure to run the migrations that reflect the entity on your database schema. But before that, transpile the TypeScript files to JavaScript files by running the build command:</p>
<pre><code class="lang-bash">npm run build
</code></pre>
<p>Once the build process is complete, run the migration using the following command:</p>
<pre><code class="lang-bash">medusa migrations run
</code></pre>
<p>By creating the referral entity and repository, you have established the foundation for managing referral data in the backend. In the subsequent sections, you will build upon this by implementing services, APIs, and event subscribers to handle referral creation, validation, and updates.</p>
<h2 id="heading-create-a-referral-service">Create a Referral Service</h2>
<p>The referral service class contains different methods for creating and saving new referrals to the database. To create a referral service, create a <code>referral.ts</code> file in the <code>src/services</code> folder and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { TransactionBaseService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>
<span class="hljs-keyword">import</span> { EntityManager } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>
<span class="hljs-keyword">import</span> ReferralRepository <span class="hljs-keyword">from</span> <span class="hljs-string">"../repositories/referral"</span>

<span class="hljs-keyword">type</span> InjectedDependencies = {
    manager: EntityManager
    referralRepository: <span class="hljs-keyword">typeof</span> ReferralRepository
}

<span class="hljs-keyword">class</span> ReferralService <span class="hljs-keyword">extends</span> TransactionBaseService {
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">readonly</span> referralRepository_: <span class="hljs-keyword">typeof</span> ReferralRepository

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">{
        referralRepository
    }: InjectedDependencies</span>) {
        <span class="hljs-built_in">super</span>(<span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>])
        <span class="hljs-built_in">this</span>.referralRepository_ = referralRepository
    }

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferralService
</code></pre>
<p>The <code>ReferralService</code> class extends the <code>TransactionBaseService</code> class. This allows the referral service to inherit and utilize the transaction-related methods and functionalities provided by the base service.</p>
<p>The constructor of the <code>ReferralService</code> class accepts an object that contains the injected dependencies. It calls the <code>super</code> method with <code>arguments[0]</code> to pass the dependencies to the parent class constructor. Additionally, it assigns the <code>referralRepository</code> to the <code>referralRepository_</code> property.</p>
<p>Next, create a method to save new referral in the database:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { TransactionBaseService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>
<span class="hljs-keyword">import</span> { Referral } <span class="hljs-keyword">from</span> <span class="hljs-string">"models/referral"</span>
<span class="hljs-keyword">import</span> { EntityManager } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>
<span class="hljs-keyword">import</span> ReferralRepository <span class="hljs-keyword">from</span> <span class="hljs-string">"../repositories/referral"</span>

<span class="hljs-comment">// Existing code here</span>

<span class="hljs-keyword">class</span> ReferralService <span class="hljs-keyword">extends</span> TransactionBaseService {
    <span class="hljs-comment">// Constructor here</span>

    <span class="hljs-keyword">async</span> create(referral: CreateReferralInput): <span class="hljs-built_in">Promise</span>&lt;Referral&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.atomicPhase_(<span class="hljs-keyword">async</span> (manager) =&gt; {
            <span class="hljs-keyword">const</span> referralRepository = manager.withRepository(
                <span class="hljs-built_in">this</span>.referralRepository_
            )
            <span class="hljs-keyword">const</span> created = referralRepository.create(referral);
            <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> referralRepository.save(created);

            <span class="hljs-keyword">return</span> result;
        })
    }

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferralService
</code></pre>
<p>The asynchronous <code>create</code> method creates and saves a <code>Referral</code> entity. It follows an atomic and transactional approach to ensure data integrity.</p>
<p>Within the function, the <code>atomicPhase_</code> method is used to encapsulate the operations, ensuring that they are executed atomically. The method takes a callback function with a <code>manager</code> parameter, which represents the TypeORM <code>EntityManager</code> instance responsible for managing database transactions.</p>
<p>Inside the callback function, a <code>referralRepository</code> variable is created by associating the <code>this.referralRepository_</code> with the current transaction using the <code>manager.withRepository()</code> method. This ensures that the repository operations are performed within the transaction context.</p>
<p>The function then proceeds to create a new <code>Referral</code> entity by invoking <code>referralRepository.create(referral)</code>. This prepares the entity with the provided data.</p>
<p>Next, the <code>created</code> entity is passed to <code>referralRepository.save(created)</code> to persist in the database. This triggers the actual database operation to insert the entity. Finally, the function returns a promise that resolves to the result of the <code>referralRepository.save()</code> operation, which is the saved <code>Referral</code> object.</p>
<h3 id="heading-create-a-custom-input-type-for-referral">Create a Custom Input Type for Referral</h3>
<p>The <code>create</code> method takes a <code>referral</code> argument of <code>CreateReferralInput</code> type which hasn't been created yet. Create a <code>referral.ts</code> file in the <code>src/types</code> directory to store this custom input type:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Customer } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa/dist/models/customer"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> CreateReferralInput = {
    referral_code?: <span class="hljs-built_in">string</span>
    referrer_customer?: Customer
}
</code></pre>
<p>The <code>CreateReferralInput</code> type defines the structure of the input object when creating a referral. It includes two optional properties: <code>referral_code</code> (representing the referral code) and <code>referrer_customer</code> (representing the referrer customer associated with the referral).</p>
<p>The final updated referral service looks like the below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { TransactionBaseService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>
<span class="hljs-keyword">import</span> { Referral } <span class="hljs-keyword">from</span> <span class="hljs-string">"models/referral"</span>
<span class="hljs-keyword">import</span> { EntityManager } <span class="hljs-keyword">from</span> <span class="hljs-string">"typeorm"</span>
<span class="hljs-keyword">import</span> { CreateReferralInput } <span class="hljs-keyword">from</span> <span class="hljs-string">"types/referral"</span>
<span class="hljs-keyword">import</span> ReferralRepository <span class="hljs-keyword">from</span> <span class="hljs-string">"../repositories/referral"</span>

<span class="hljs-keyword">type</span> InjectedDependencies = {
    manager: EntityManager
    referralRepository: <span class="hljs-keyword">typeof</span> ReferralRepository
}

<span class="hljs-keyword">class</span> ReferralService <span class="hljs-keyword">extends</span> TransactionBaseService {
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">readonly</span> referralRepository_: <span class="hljs-keyword">typeof</span> ReferralRepository

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">{
        referralRepository
    }: InjectedDependencies</span>) {
        <span class="hljs-built_in">super</span>(<span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>])
        <span class="hljs-built_in">this</span>.referralRepository_ = referralRepository
    }

    <span class="hljs-keyword">async</span> create(referral: CreateReferralInput): <span class="hljs-built_in">Promise</span>&lt;Referral&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.atomicPhase_(<span class="hljs-keyword">async</span> (manager) =&gt; {
            <span class="hljs-keyword">const</span> referralRepository = manager.withRepository(
                <span class="hljs-built_in">this</span>.referralRepository_
            )
            <span class="hljs-keyword">const</span> created = referralRepository.create(referral);
            <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> referralRepository.save(created);

            <span class="hljs-keyword">return</span> result;
        })
    }

}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferralService
</code></pre>
<h2 id="heading-create-a-subscriber-for-referral-code-creation">Create a Subscriber for Referral Code Creation</h2>
<p>You can utilize the event-driven architecture of Medusa to implement the functionality of generating a new referral code for each customer upon registration. When a customer registers on the application, the <code>customer.created</code> <a target="_blank" href="https://docs.medusajs.com/development/events/events-list">event</a> is triggered. This event serves as a trigger point for executing custom logic. In this case, you would create a subscriber that is responsible for handling this event and generating a new referral code for the customer.</p>
<blockquote>
<p>Learn how you can create a subscriber in Medusa in their <a target="_blank" href="https://docs.medusajs.com/development/events/create-subscriber">official documentation</a>.</p>
</blockquote>
<p>Create a <code>newReferralCode.ts</code> file in the <code>src/subscribers</code> directory and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CustomerService, EventBusService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>;
<span class="hljs-keyword">import</span> ReferralService <span class="hljs-keyword">from</span> <span class="hljs-string">"../services/referral"</span>;

<span class="hljs-keyword">type</span> InjectedProperties = {
    eventBusService: EventBusService
    referralService: ReferralService
    customerService: CustomerService
}

<span class="hljs-keyword">class</span> NewReferralCodeSubscriber {
    <span class="hljs-keyword">private</span> referralService: ReferralService
    <span class="hljs-keyword">private</span> customerService: CustomerService

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">properties: InjectedProperties</span>) {
        <span class="hljs-built_in">this</span>.referralService = properties.referralService;
        <span class="hljs-built_in">this</span>.customerService = properties.customerService;
        properties.eventBusService.subscribe(<span class="hljs-string">"customer.created"</span>, <span class="hljs-built_in">this</span>.assignNewReferralCode);
    }

    assignNewReferralCode = <span class="hljs-keyword">async</span> (customer) =&gt; {

        <span class="hljs-comment">// Generate new referral code</span>
        <span class="hljs-keyword">let</span> newReferralCode = <span class="hljs-built_in">this</span>.generateReferralCode(<span class="hljs-number">6</span>);

        <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.referralService.create({
            referral_code: newReferralCode,
            referrer_customer: customer
        })

        <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerService.update(customer.id, {
            metadata: { <span class="hljs-string">"referral_code"</span>: newReferralCode }
        })
    }

    generateReferralCode = <span class="hljs-function">(<span class="hljs-params">length</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> characters = <span class="hljs-string">'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'</span>;
        <span class="hljs-keyword">const</span> codeLength = length || <span class="hljs-number">6</span>;
        <span class="hljs-keyword">let</span> referralCode = <span class="hljs-string">''</span>;

        <span class="hljs-keyword">while</span> (referralCode.length &lt; codeLength) {
            <span class="hljs-keyword">const</span> randomIndex = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * characters.length);
            <span class="hljs-keyword">const</span> randomCharacter = characters.charAt(randomIndex);
            referralCode += randomCharacter;
        }

        <span class="hljs-keyword">return</span> referralCode;
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewReferralCodeSubscriber;
</code></pre>
<p>The <code>NewReferralCodeSubscriber</code> relies on several injected services: <code>EventBusService</code> from Medusa, <code>ReferralService</code>, and <code>CustomerService</code>. Upon instantiation, the <code>NewReferralCodeSubscriber</code> class assigns the injected services to their private properties. It subscribes to the <code>customer.created</code> event using the <code>eventBusService.subscribe</code> method and provides the <code>assignNewReferralCode</code> method as the event handler.</p>
<p>The <code>assignNewReferralCode</code> method is an asynchronous function that receives the <code>customer</code> object as its parameter. It generates a new referral code by invoking the <code>generateReferralCode</code> method. The generated code is then used to create a new referral entry through the <code>referralService.create</code> method, which associates the referral code with the customer.</p>
<p>The <code>generateReferralCode</code> method is a utility function used to generate a random alphanumeric code. It takes an optional <code>length</code> parameter to determine the length of the referral code. It iteratively selects random characters from a predefined character set, concatenating them to form the referral code.</p>
<p>Additionally, the handler also updates the customer's metadata with the newly generated referral code using the <code>customerService.update</code> method.</p>
<h2 id="heading-setting-up-the-medusa-storefront">Setting up the Medusa Storefront</h2>
<p>The next task is to let the users enter a referral code while registering on the application. To implement this, you'd need to set up the Medusa Storefront. In this tutorial, you will set up the <a target="_blank" href="https://docs.medusajs.com/starters/nextjs-medusa-starter">Next.js</a> storefront offered by Medusa.</p>
<p>To begin, create a new Next.js project using the Medusa starter template by running the following command:</p>
<pre><code class="lang-bash">npx create-next-app -e https://github.com/medusajs/nextjs-starter-medusa my-medusa-storefront
</code></pre>
<p>After the project is created, navigate to the newly created directory and rename the template environment variable file to use environment variables in development:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-medusa-storefront
mv .env.template .env.local
</code></pre>
<p>Ensure that the Medusa server is running, and then start the storefront by running the following command:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>This command will start the development server for the Medusa storefront on <code>localhost:8000</code>, allowing you to test and interact with the application locally.</p>
<h2 id="heading-add-referral-code-field-in-registration-form">Add Referral Code Field in Registration Form</h2>
<p>Now that your storefront is set up successfully, it's time to add the referral code field to the registration form.</p>
<p>Open the <code>src/modules/account/components/register/index.tsx</code> file and add a <code>referral_code</code> property in the <code>RegisterCredentials</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> RegisterCredentials <span class="hljs-keyword">extends</span> FieldValues {
  ...
  referral_code?: <span class="hljs-built_in">string</span>
}
</code></pre>
<p>Next, in the <code>Register</code> component, add the input field for the referral code after the password input field:</p>
<pre><code class="lang-typescript">&lt;Input
  label=<span class="hljs-string">"Have a referral code?"</span>
  {...register(<span class="hljs-string">"referral_code"</span>)}
  autoComplete=<span class="hljs-string">"off"</span>
  errors={errors}
/&gt;
</code></pre>
<p>At this point, the register page should look like the below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686325197211/6334a3d4-ba9b-4ac0-afeb-e579a271d9ba.png" alt="Updated Register Page" class="image--center mx-auto" /></p>
<p>The <code>customers.create</code> method doesn't accept the referral code by default. Thus, before passing the credentials to the method, you'd need to extract the referral code from it as below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> onSubmit = handleSubmit(<span class="hljs-keyword">async</span> (credentials) =&gt; {
    <span class="hljs-keyword">const</span> { referral_code, ...registerCredentials } = credentials

    <span class="hljs-keyword">await</span> medusaClient.customers
      .create(registerCredentials)
      .then(<span class="hljs-function">() =&gt;</span> {
        refetchCustomer()
        router.push(<span class="hljs-string">"/account"</span>)
      })
      .catch(handleError)
  })
</code></pre>
<p>In the above code, the <code>credentials</code> object is destructured to extract the <code>referral_code</code> value and the remaining <code>registerCredentials</code>. Then, you pass the <code>registerCredentials</code> to the <code>create</code> method.</p>
<h2 id="heading-implement-the-referral-code-validation-api">Implement the Referral Code Validation API</h2>
<p>When the user enters a referral code, you must check whether the referral code entered by the user is valid and associated with any customer. To do this, you'd create an API endpoint in the backend, and make a call from the frontend.</p>
<p>Open the <code>src/api/index.ts</code> file and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Router } <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (rootDirectory: <span class="hljs-built_in">string</span>): Router | Router[] =&gt; {

  <span class="hljs-keyword">const</span> router = Router()

  <span class="hljs-comment">// add your custom routes here</span>

  router.get(<span class="hljs-string">"/store/referral/:referralCode"</span>,
    <span class="hljs-keyword">async</span> (req, res) =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> referralService = req.scope.resolve(<span class="hljs-string">"referralService"</span>);

        <span class="hljs-keyword">const</span> referralCode = req.params.referralCode;

        <span class="hljs-keyword">const</span> referral = <span class="hljs-keyword">await</span> referralService.getByCode(referralCode);

        <span class="hljs-keyword">if</span> (referral) {
          res.json(referral);
        } <span class="hljs-keyword">else</span> {
          res.status(<span class="hljs-number">404</span>).json({ error: <span class="hljs-string">"Referral not found"</span> })
        }
      } <span class="hljs-keyword">catch</span> (error) {
        res.status(<span class="hljs-number">500</span>).json({ error: <span class="hljs-string">"Internal server error"</span> });
      }
    }
  )

  <span class="hljs-keyword">return</span> router;
}
</code></pre>
<p>In the above code, you create a GET endpoint at <code>/store/referral/:referralCode</code> . This endpoint expects a referral code as a parameter in the URL.</p>
<p>The <code>referralService</code> is used to retrieve the referral object corresponding to the given referral code using the <code>getByCode</code> method. If a referral is found, it is returned as a JSON response using <code>res.json(referral)</code>. Otherwise, if no referral is found, a 404 status code with an error message is sent as the response.</p>
<p>In case of any errors during the execution of the callback or the retrieval process, a generic error message with a 500 status code is returned.</p>
<blockquote>
<p>Learn more about creating an endpoint in Medusa in their <a target="_blank" href="https://docs.medusajs.com/development/endpoints/create">official documentation</a>.</p>
</blockquote>
<h3 id="heading-cors-configuration">CORS Configuration</h3>
<p>Since you'll be using the storefront to make a request on the above-created endpoint, you need to pass your endpoints Cross-Origin Resource Origin (CORS) options using the <code>cors</code> package.</p>
<ol>
<li><p>Begin by importing the necessary utility functions and types from Medusa's packages along with the <code>cors</code> library:</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">import</span> { getConfigFile, parseCorsOrigins } <span class="hljs-keyword">from</span> <span class="hljs-string">"medusa-core-utils"</span>;
 <span class="hljs-keyword">import</span> { ConfigModule } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa/dist/types/global"</span>;
 <span class="hljs-keyword">import</span> cors <span class="hljs-keyword">from</span> <span class="hljs-string">"cors"</span>;
</code></pre>
</li>
<li><p>In the exported function, retrieve the CORS configurations of your backend using the utility functions you imported:</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (rootDirectory: <span class="hljs-built_in">string</span>): Router | Router[] =&gt; {
   <span class="hljs-keyword">const</span> { configModule } =
     getConfigFile&lt;ConfigModule&gt;(rootDirectory, <span class="hljs-string">"medusa-config"</span>)
   <span class="hljs-keyword">const</span> { projectConfig } = configModule

   <span class="hljs-comment">// ...</span>
 }
</code></pre>
</li>
<li><p>Create an object to hold the CORS configurations. Since it's a storefront endpoint, pass the origins specified in the <code>store_cors</code> property of the project configuration:</p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">const</span> corsOptions = {
   origin: projectConfig.store_cors.split(<span class="hljs-string">","</span>),
   credentials: <span class="hljs-literal">true</span>,
 };
</code></pre>
</li>
<li><p>For the route you added, create an OPTIONS request and add <code>cors</code> as middleware for the route, passing it the CORS options:</p>
<pre><code class="lang-typescript"> router.options(<span class="hljs-string">"/store/referral/:referralCode"</span>, cors(corsOptions))
 router.get(<span class="hljs-string">"/store/referral/:referralCode"</span>, cors(corsOptions),
   <span class="hljs-keyword">async</span> (req, res) =&gt; {
     <span class="hljs-comment">// ...</span>
 });
</code></pre>
</li>
</ol>
<h3 id="heading-the-getbycode-service-method">The <code>getByCode</code> Service Method</h3>
<p>If you noticed above, you have used a <code>getByCode</code> method from the referral service. But you haven't defined it yet. Open the <code>src/services/referral.ts</code> file and add the following method to the <code>ReferralService</code> class:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> ReferralService <span class="hljs-keyword">extends</span> TransactionBaseService {
    ...

    <span class="hljs-keyword">async</span> getByCode(referralCode: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">Promise</span>&lt;Referral&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.atomicPhase_(<span class="hljs-keyword">async</span> (manager) =&gt; {
            <span class="hljs-keyword">const</span> referralRepository = manager.withRepository(
                <span class="hljs-built_in">this</span>.referralRepository_
            )
            <span class="hljs-keyword">const</span> referral = <span class="hljs-keyword">await</span> referralRepository
                .createQueryBuilder(<span class="hljs-string">"referral"</span>)
                .leftJoinAndSelect(<span class="hljs-string">"referral.referrer_customer"</span>, <span class="hljs-string">"referrer_customer"</span>)
                .where(<span class="hljs-string">"referral.referral_code = :referralCode"</span>, { referralCode })
                .getOne();

            <span class="hljs-keyword">return</span> referral;
        })
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferralService
</code></pre>
<p>The above code defines an <code>async</code> function named <code>getByCode</code> that retrieves a referral based on a given referral code.</p>
<p>A query builder is utilized to construct a query for retrieving the referral. It performs a left join with the <code>referrer_customer</code> entity, allowing the referral's associated customer data to be included in the result.</p>
<p>The query filters the referrals based on the provided <code>referralCode</code> using the <code>where</code> clause. It retrieves only one referral using the <code>getOne</code> method, indicating that the referral code is expected to be unique.</p>
<p>Once the referral is retrieved, it is returned as the result of the <code>getByCode</code> function.</p>
<h3 id="heading-using-the-api-to-validate-the-referral-code">Using the API To Validate the Referral Code</h3>
<p>Now that you have created the API endpoint to validate the referral code, you'd need to use it in the storefront. Open the file and update the <code>onSubmit</code> function as below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> onSubmit = handleSubmit(<span class="hljs-keyword">async</span> (credentials) =&gt; {
  <span class="hljs-keyword">let</span> referrerCustomerId: <span class="hljs-built_in">string</span> = <span class="hljs-string">""</span>
  <span class="hljs-keyword">const</span> { referral_code, ...registerCredentials } = credentials
  <span class="hljs-keyword">if</span> (referral_code) {
    referrerCustomerId = <span class="hljs-keyword">await</span> getReferrerCustomerId(referral_code)
    <span class="hljs-keyword">if</span> (!referrerCustomerId) {
      <span class="hljs-keyword">return</span>
    }
  }

  <span class="hljs-keyword">await</span> medusaClient.customers
    .create(registerCredentials)
    .then(<span class="hljs-function">() =&gt;</span> {
      refetchCustomer()
      router.push(<span class="hljs-string">"/account"</span>)
    })
    .catch(handleError)
})
</code></pre>
<p>The above code uses a <code>getReferrerCustomerId</code> function to get the referrer customer's ID. If no referrer's customer ID is found, the function returns early.</p>
<p>Next, create the <code>getReferrerCustomerId</code> function where you send a GET request on the newly created API endpoint:</p>
<pre><code class="lang-typescript">  <span class="hljs-keyword">const</span> [referralError, setReferralError] = useState&lt;<span class="hljs-built_in">string</span> | <span class="hljs-literal">undefined</span>&gt;(<span class="hljs-literal">undefined</span>)

  <span class="hljs-keyword">const</span> getReferrerCustomerId = <span class="hljs-keyword">async</span> (referralCode: <span class="hljs-built_in">string</span>) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
        <span class="hljs-string">`http://localhost:9000/store/referral/<span class="hljs-subst">${referralCode}</span>`</span>
      )

      <span class="hljs-keyword">if</span> (!response.ok) {
        setReferralError(<span class="hljs-string">"The referral code is invalid. Please check."</span>)
        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
      }
      <span class="hljs-keyword">const</span> referral = <span class="hljs-keyword">await</span> response.json()

      <span class="hljs-keyword">return</span> referral.referrer_customer.id
    } <span class="hljs-keyword">catch</span> (error) {
      setReferralError(
        <span class="hljs-string">"An error occurred while validating the referral code. Please try again."</span>
      )
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>
    }
  }
</code></pre>
<p>In the above code, you first initialize a state variable for the referral error that may occur while handling the API request.</p>
<p>Next, the <code>getReferrerCustomerId</code> function is an asynchronous function that takes a <code>referralCode</code> parameter. Within the function, it attempts to make a GET request on the API endpoint with the referral code as a parameter.</p>
<p>If the response received from the server indicates an error (not a 2xx status code), the <code>setReferralError</code> function is called to update the <code>referralError</code> state with an appropriate error message. The function then returns <code>null</code> to indicate an invalid referral code.</p>
<p>If the response is successful, the function parses the response body as JSON using <code>response.json()</code>. It assumes that the response body contains the referral object. The function then returns the ID of the referrer's customer extracted from the parsed referral object.</p>
<p>If any error occurs during the HTTP request or JSON parsing, the <code>catch</code> block is executed. It sets the <code>referralError</code> state to an error message indicating that an error occurred while validating the referral code. The function returns <code>null</code> to indicate the validation failure.</p>
<p>You can use the <code>referralError</code> state variable in the <code>Register</code> component to display the referral-related errors as below:</p>
<pre><code class="lang-typescript">{referralError &amp;&amp; (
  &lt;div&gt;
    &lt;span className=<span class="hljs-string">"text-rose-500 w-full text-small-regular"</span>&gt;
      {referralError}
    &lt;/span&gt;
  &lt;/div&gt;
)}
</code></pre>
<h3 id="heading-display-the-customers-referral-code">Display the Customer’s Referral Code</h3>
<p>Ideally, a customer should be able to view its referral code and share it with others. But as of now, the customer cannot view it.</p>
<p>Open the <code>src/modules/account/components/overview/index.tsx</code> file in the storefront and add the following code:</p>
<pre><code class="lang-typescript">&lt;div className=<span class="hljs-string">"flex flex-col gap-y-4"</span>&gt;
  &lt;div className=<span class="hljs-string">"flex items-center gap-x-2"</span>&gt;
    &lt;h3 className=<span class="hljs-string">"text-large-semi"</span>&gt;Referral Details&lt;/h3&gt;
  &lt;/div&gt;
  &lt;p&gt;
    Your referral code is{<span class="hljs-string">" "</span>}
    &lt;strong&gt;{customer?.metadata[<span class="hljs-string">"referral_code"</span>] || <span class="hljs-string">"loading..."</span>}&lt;/strong&gt;.
   &lt;/p&gt;
&lt;/div&gt;
</code></pre>
<p>If you remember, in one of the previous sections, you had stored the <code>referral_code</code> in the customer's <code>metdata</code>. In the above code, you used the customer's <code>metadata</code> to get the value of <code>referral_code</code> key.</p>
<h2 id="heading-demo-using-referal-code-while-registration">Demo: Using Referal Code While Registration</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/eydh63jq6xQ">https://youtu.be/eydh63jq6xQ</a></div>
<p> </p>
<p>In the above demo, the process begins with a regular user signing up for an account without using a referral code. Once the registration is complete, the customer gains access to their profile where they can find their unique referral code and share it.</p>
<p>Following that, another user attempts to register for an account. Initially, this user enters an invalid referral code, resulting in an error message. However, upon entering a valid referral code, the registration process is successful, and the user can now view their own referral code within their account.</p>
<p>In the upcoming sections, you'll implement the discounting logic for the referrer and referred customers.</p>
<h2 id="heading-implementing-discounts-for-the-referrer-and-referred-customers">Implementing Discounts for the Referrer and Referred Customers</h2>
<p>Implementing discounts for the referrer and referred customers involves setting up a system where customers who refer others receive discounts, and the referred customers also receive their own discounts.</p>
<p>Here's a breakdown of the approach you're going to follow:</p>
<ol>
<li><p>Frontend Implementation:</p>
<ul>
<li><p>When a user enters a referral code during registration, the frontend will send a request to the <code>/store/referral/:referralCode</code> API endpoint to retrieve the referrer customer's ID.</p>
</li>
<li><p>After the account is created, the frontend will obtain the referred customer's ID.</p>
</li>
</ul>
</li>
<li><p>Backend Implementation:</p>
<ul>
<li><p>You will create a new API endpoint <code>/store/referral/discounts</code> that accepts the referrer and referred customer IDs as a POST request.</p>
</li>
<li><p>This endpoint will trigger two events internally: <code>referrer-discount.update</code> and <code>referred-discount.update</code>.</p>
</li>
<li><p>In the backend, you will create two subscribers for these events, which will add the referrer and referred customers to their respective customer groups: "Referrer Customers" and "Referred Customers".</p>
</li>
</ul>
</li>
<li><p>Medusa Admin Configuration:</p>
<ul>
<li>Using the Medusa Admin, you can configure the appropriate discounts for the referrer and referred customers. These discounts can be applied to their respective customer groups.</li>
</ul>
</li>
<li><p>Tracking Referral Count:</p>
<ul>
<li><p>You will maintain a <code>total_referrals</code> key in the customer's metadata. This key will represent the total number of customers who have successfully used a customer's referral code.</p>
</li>
<li><p>Whenever a customer uses the discount referral discount applicable to it, the <code>total_referrals</code> count will decrease by 1.</p>
</li>
<li><p>Similarly, when a customer signs up using a referral code, the <code>total_referrals</code> count will increase by 1.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-frontend-implementation">Frontend Implementation</h3>
<p>To implement the functionality in the front end, as previously mentioned, the first step is to retrieve the IDs of the referred and referrer customers. Once obtained, you can proceed with making a POST request to the designated API endpoint. This section will guide you through the necessary steps to implement this process in the front end of your application.</p>
<p>Open the <code>src/modules/account/components/register/index.tsx</code> and update the <code>onSubmit</code> method as below:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> onSubmit = handleSubmit(<span class="hljs-keyword">async</span> (credentials) =&gt; {
    <span class="hljs-keyword">let</span> referrerCustomerId: <span class="hljs-built_in">string</span> = <span class="hljs-string">""</span>
    <span class="hljs-keyword">const</span> { referral_code, ...registerCredentials } = credentials
    <span class="hljs-keyword">if</span> (referral_code) {
      referrerCustomerId = <span class="hljs-keyword">await</span> getReferrerCustomerId(referral_code)
      <span class="hljs-keyword">if</span> (!referrerCustomerId) {
        <span class="hljs-keyword">return</span>
      }
    }

    <span class="hljs-keyword">let</span> referredCustomerId: <span class="hljs-built_in">string</span> = <span class="hljs-string">""</span>

    <span class="hljs-keyword">await</span> medusaClient.customers
      .create(registerCredentials)
      .then(<span class="hljs-function">(<span class="hljs-params">{ customer }</span>) =&gt;</span> {
        referredCustomerId = customer.id
        refetchCustomer()
        router.push(<span class="hljs-string">"/"</span>)
        updateDiscounts(referredCustomerId, referrerCustomerId)
      })
      .catch(handleError)
  })
</code></pre>
<p>In the above code, you declare a <code>referredCustomerId</code> variable and initialize it as an empty string. If the customer creation is successful, the <code>then()</code> block is executed, and the customer object is destructured from the response as <code>{ customer }</code>. The <code>referredCustomerId</code> is assigned the value of the newly created customer's ID.</p>
<p>Finally, you invoke the <code>updateDiscounts(referredCustomerId, referrerCustomerId)</code> function to initiate updating discounts for the referred and referrer customers, passing their respective IDs.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> updateDiscounts = <span class="hljs-keyword">async</span> (
    referredCustomerId: <span class="hljs-built_in">string</span>,
    referrerCustomerId: <span class="hljs-built_in">string</span>
  ) =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(
        <span class="hljs-string">"http://localhost:9000/store/referral/discounts"</span>,
        {
          method: <span class="hljs-string">"POST"</span>,
          headers: {
            <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
          },
          body: <span class="hljs-built_in">JSON</span>.stringify({ referredCustomerId, referrerCustomerId }),
        }
      )

      <span class="hljs-keyword">if</span> (response.ok) {
        <span class="hljs-keyword">const</span> responseData = <span class="hljs-keyword">await</span> response.json()
        <span class="hljs-built_in">console</span>.log(responseData) <span class="hljs-comment">// Handle the response data as needed</span>
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">const</span> errorData = <span class="hljs-keyword">await</span> response.json()
        <span class="hljs-built_in">console</span>.error(errorData) <span class="hljs-comment">// Handle the error response</span>
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"An error occurred while updating discounts"</span>, error) <span class="hljs-comment">// Handle any other errors</span>
    }
  }
</code></pre>
<p>The above code defines an asynchronous function called <code>updateDiscounts</code>, which is responsible for making a POST request to update discounts for the referred and referrer customers.</p>
<p>The function uses the <code>fetch()</code> function to send a POST request to the <code>/store/referral/discounts</code> endpoint. The request includes the <code>referredCustomerId</code> and <code>referrerCustomerId</code> values in the request body as a JSON payload.</p>
<h3 id="heading-backend-implementation">Backend Implementation</h3>
<p>Let's create the <code>/store/referral/discounts</code> API endpoint in the backend. Open the <code>src/api/index.ts</code> file and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">"body-parser"</span>)

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (rootDirectory: <span class="hljs-built_in">string</span>): Router | Router[] =&gt; {

  <span class="hljs-comment">// ...</span>

  <span class="hljs-keyword">const</span> router = Router()
  router.use(bodyParser.json());

  <span class="hljs-comment">// add your custom routes here</span>

  <span class="hljs-comment">// ...</span>

  router.options(<span class="hljs-string">"/store/referral/discounts"</span>, cors(corsOptions))
  router.post(<span class="hljs-string">"/store/referral/discounts"</span>, cors(corsOptions),
    <span class="hljs-keyword">async</span> (req, res) =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> eventBusService = req.scope.resolve(<span class="hljs-string">"eventBusService"</span>);
        <span class="hljs-keyword">const</span> customerService = req.scope.resolve(<span class="hljs-string">"customerService"</span>);

        <span class="hljs-keyword">const</span> { referredCustomerId, referrerCustomerId } = req.body;

        <span class="hljs-keyword">if</span> (referrerCustomerId) {
          eventBusService.emit(<span class="hljs-string">"referred-discount.update"</span>, { referredCustomerId });
          eventBusService.emit(<span class="hljs-string">"referrer-discount.update"</span>, { referrerCustomerId });
          <span class="hljs-keyword">const</span> referrerCustomer = <span class="hljs-keyword">await</span> customerService.retrieve(referrerCustomerId)

          <span class="hljs-keyword">const</span> totalReferrals = referrerCustomer.metadata
            &amp;&amp; <span class="hljs-keyword">typeof</span> referrerCustomer.metadata.total_referrals === <span class="hljs-string">"number"</span>
            ? referrerCustomer.metadata.total_referrals
            : <span class="hljs-number">0</span>;

          <span class="hljs-keyword">await</span> customerService.update(referrerCustomerId, {
            metadata: {
              <span class="hljs-string">"total_referrals"</span>: totalReferrals + <span class="hljs-number">1</span>
            }
          })
        }
        res.json({ success: <span class="hljs-literal">true</span> });
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.log(error);

        res.status(<span class="hljs-number">500</span>).json({ error: <span class="hljs-string">"Internal server error"</span> });
      }
    }
  )

  <span class="hljs-keyword">return</span> router;
}
</code></pre>
<p>The above code defines an API endpoint that handles updating discounts for referred and referrer customers. When a POST request is made to the <code>/store/referral/discounts</code> endpoint, the code retrieves the required services and data from the request.</p>
<p>Since you're creating a POST endpoint, you'd need to import the <code>body-parser</code> library and use it.</p>
<p>If a referrer customer ID is provided, the code emits events to update the discounts for both the referred and referrer customers. It also retrieves the referrer customer's metadata, increments the total referral count, and updates the metadata accordingly. This condition check is important because you don't want to emit the events if the customer hasn't been referred by other customers.</p>
<p>Finally, a success response is sent back to the client. If any errors occur, an error response is returned. Overall, this code facilitates the process of updating discounts and tracking the number of referrals for customers.</p>
<h2 id="heading-subscribers-implementation">Subscribers Implementation</h2>
<p>Now, you need two subscribers that listen to the events emitted by the API endpoint. The subscribers add the customers to their respective customer groups.</p>
<h4 id="heading-the-referrer-customers-customer-group">The "Referrer Customers" Customer Group</h4>
<p>Create a <code>referrerCustomerGroupAssignment.ts</code> file in the <code>src/subscribers</code> directory and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CustomerGroupService, EventBusService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>


<span class="hljs-keyword">type</span> InjectedProperties = {
    eventBusService: EventBusService
    customerGroupService: CustomerGroupService
}


<span class="hljs-keyword">class</span> ReferrerCustomerGroupAssignmentSubscriber {
    <span class="hljs-keyword">private</span> customerGroupService: CustomerGroupService
    <span class="hljs-keyword">private</span> customerGroupName: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">properties: InjectedProperties</span>) {
        <span class="hljs-built_in">this</span>.customerGroupService = properties.customerGroupService;
        <span class="hljs-built_in">this</span>.customerGroupName = <span class="hljs-string">"Referrer Customers"</span>;
        properties.eventBusService.subscribe(<span class="hljs-string">"referrer-discount.update"</span>, <span class="hljs-built_in">this</span>.handleGroupAssignment);
    }

    handleGroupAssignment = <span class="hljs-keyword">async</span> ({ referrerCustomerId }) =&gt; {

        <span class="hljs-keyword">let</span> customerGroup;

        <span class="hljs-comment">// Check if "Referrer Customers" customer group exists</span>
        <span class="hljs-keyword">let</span> customerGroupList = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.list({ name: <span class="hljs-built_in">this</span>.customerGroupName }, { take: <span class="hljs-number">1</span> });

        <span class="hljs-comment">// If it doesn't exist, create it</span>
        <span class="hljs-keyword">if</span> (!customerGroupList.length) {
            customerGroup = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.create({ name: <span class="hljs-built_in">this</span>.customerGroupName });
        } <span class="hljs-keyword">else</span> {
            customerGroup = customerGroupList[<span class="hljs-number">0</span>];
        }

        customerGroup = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.retrieve(customerGroup.id, { relations: [<span class="hljs-string">"customers"</span>] })

        <span class="hljs-keyword">const</span> isCustomerInGroup = customerGroup.customers.some(
            <span class="hljs-function">(<span class="hljs-params">customer</span>) =&gt;</span> customer.id === referrerCustomerId
        );

        <span class="hljs-keyword">if</span> (isCustomerInGroup) <span class="hljs-keyword">return</span>;

        <span class="hljs-comment">// Add customer to "Referrer Customers" customer group</span>
        <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.addCustomers(customerGroup.id, [referrerCustomerId]);
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferrerCustomerGroupAssignmentSubscriber;
</code></pre>
<p>The above code defines a class called <code>ReferrerCustomerGroupAssignmentSubscriber</code>. This class is responsible for assigning customers to the "Referrer Customers" customer group when a referral discount is updated.</p>
<p>The class has a constructor that receives <code>InjectedProperties</code> as input, which includes the <code>eventBusService</code> and <code>customerGroupService</code> from the Medusa library. In the constructor, the <code>eventBusService</code> is used to subscribe to the event <code>referrer-discount.update</code> and associate it with the <code>handleGroupAssignment</code> method.</p>
<p>The <code>handleGroupAssignment</code> method is triggered when the <code>referrer-discount.update</code> event is emitted. It retrieves the <code>referrerCustomerId</code> from the event payload.</p>
<p>The code then checks if the "Referrer Customers" customer group already exists by listing customer groups with the specified name. If it doesn't exist, a new customer group is created using the <code>customerGroupService</code>.</p>
<p>Next, the code retrieves the customer group and its associated customers. It checks if the <code>referrerCustomerId</code> is already present in the customer group. If the customer is already in the group, the method returns early. If the customer is not in the group, the <code>referrerCustomerId</code> is added to the "Referrer Customers" customer group using the <code>customerGroupService</code>.</p>
<h4 id="heading-the-referred-customers-customer-group">The "Referred Customers" Customer Group</h4>
<p>Create a <code>referredCustomerGroupAssignment.ts</code> file in the <code>src/subscribers</code> directory and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CustomerGroupService, EventBusService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>


<span class="hljs-keyword">type</span> InjectedProperties = {
    eventBusService: EventBusService
    customerGroupService: CustomerGroupService
}


<span class="hljs-keyword">class</span> ReferredCustomerGroupAssignmentSubscriber {
    <span class="hljs-keyword">private</span> customerGroupService: CustomerGroupService
    <span class="hljs-keyword">private</span> customerGroupName: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">properties: InjectedProperties</span>) {
        <span class="hljs-built_in">this</span>.customerGroupService = properties.customerGroupService;
        <span class="hljs-built_in">this</span>.customerGroupName = <span class="hljs-string">"Referred Customers"</span>;
        properties.eventBusService.subscribe(<span class="hljs-string">"referred-discount.update"</span>, <span class="hljs-built_in">this</span>.handleGroupAssignment);
    }

    handleGroupAssignment = <span class="hljs-keyword">async</span> ({ referredCustomerId }) =&gt; {

        <span class="hljs-keyword">let</span> customerGroup;

        <span class="hljs-comment">// Check if "Referred Customers" customer group exists</span>
        <span class="hljs-keyword">let</span> customerGroupList = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.list({ name: <span class="hljs-built_in">this</span>.customerGroupName }, { take: <span class="hljs-number">1</span> });

        <span class="hljs-comment">// If it doesn't exist, create it</span>
        <span class="hljs-keyword">if</span> (!customerGroupList.length) {
            customerGroup = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.create({ name: <span class="hljs-built_in">this</span>.customerGroupName });
        } <span class="hljs-keyword">else</span> {
            customerGroup = customerGroupList[<span class="hljs-number">0</span>];
        }

        <span class="hljs-comment">// Add customer to "Referred Customers" customer group</span>
        <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.addCustomers(customerGroup.id, [referredCustomerId]);
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ReferredCustomerGroupAssignmentSubscriber;
</code></pre>
<p>The above code defines a class called <code>ReferredCustomerGroupAssignmentSubscriber</code>. This class is responsible for assigning customers to the "Referred Customers" customer group when a referred customer discount is updated.</p>
<p>The <code>InjectedProperties</code> type specifies the injected dependencies for the class, which include the <code>eventBusService</code> and <code>customerGroupService</code>.</p>
<p>The class has a constructor that receives the <code>InjectedProperties</code> as input. It assigns the <code>customerGroupService</code> and sets the <code>customerGroupName</code> to "Referred Customers". It then subscribes to the <code>referred-discount.update</code> event using the <code>eventBusService</code> and associates it with the <code>handleGroupAssignment</code> method.</p>
<p>The <code>handleGroupAssignment</code> method is triggered when the <code>referred-discount.update</code> event is emitted. It retrieves the <code>referredCustomerId</code> from the event payload.</p>
<p>The code then checks if the "Referred Customers" customer group already exists by listing customer groups with the specified name. If it doesn't exist, a new customer group is created using the <code>customerGroupService</code>.</p>
<p>Finally, the <code>referredCustomerId</code> is added to the "Referred Customers" customer group using the <code>customerGroupService</code>.</p>
<h2 id="heading-setting-up-the-medusa-admin">Setting up the Medusa Admin</h2>
<p>You'll require the Medusa Admin to set up the coupon code discounts for the customer groups. In this section, you'll set up the Medusa Admin Dashboard.</p>
<p>To install the Medusa Admin Dashboard in your Medusa backend directory, run the following command:</p>
<pre><code class="lang-typescript">npm install <span class="hljs-meta">@medusajs</span>/admin
</code></pre>
<p>Next, open the <code>medusa-config.js</code> file in your Medusa backend directory. Inside the <code>plugins</code> array, add the following configuration for the Admin plugin:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> plugins = [
  <span class="hljs-comment">// ...</span>
  {
    resolve: <span class="hljs-string">"@medusajs/admin"</span>,
    <span class="hljs-comment">/** @type {import('@medusajs/admin').PluginOptions} */</span>
    options: {
      <span class="hljs-comment">// ...</span>
    },
  },
]
</code></pre>
<blockquote>
<p>Check out the different <a target="_blank" href="https://docs.medusajs.com/admin/quickstart#step-2-add-admin-to-medusa-configurations">options</a> accepted by the admin plugin.</p>
</blockquote>
<p>Test the admin dashboard by running the following command in the directory of the Medusa backend:</p>
<pre><code class="lang-bash">medusa develop
</code></pre>
<p>The Admin Dashboard will be available on the URL <a target="_blank" href="http://localhost:9000/app"><code>localhost:9000/app</code></a> . Since you've already seeded the data, you can use the email <code>admin@medusa-test.com</code> and password <code>supersecret</code> to log in.</p>
<h2 id="heading-creating-discounts-using-admin-dashboard">Creating Discounts using Admin Dashboard</h2>
<p>In this section, you'll create two customer groups - Referrer Customers and Referred Customers, using the Admin Dashboard. Next, you'll create a discount coupon code for each of the customer groups.</p>
<p>Follow the video to see how you can do it:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/A6aC5s_oBo4">https://youtu.be/A6aC5s_oBo4</a></div>
<p> </p>
<p>In the video, the following two referral discount coupon codes are created:</p>
<ol>
<li><p>NEW10 - 10% discount applicable for the new customers who used a valid referral code during registration</p>
</li>
<li><p>REFER20 - 20% discount applicable for customers whose referral code was used during registration</p>
</li>
</ol>
<h2 id="heading-tracking-referral-discounts">Tracking Referral Discounts</h2>
<p>Since you maintain a <code>total_referrals</code> count in the customer's metadata, you would need to update it once the user applies the "REFER20" or "NEW10" coupon code and places an order.</p>
<p>To update the <code>total_referrals</code> count and manage customer groups based on coupon codes, you can implement the following logic:</p>
<ol>
<li><p>For referred customers:</p>
<ul>
<li>If they apply the "NEW10" coupon code, remove the customer from the "Referred Customers" customer group.</li>
</ul>
</li>
<li><p>For referrer customers:</p>
<ul>
<li><p>If they apply the "REFER20" coupon code, reduce the <code>total_referrals</code> count by 1.</p>
</li>
<li><p>If the <code>total_referrals</code> count was previously 1, set it to 0, and remove the customer from the "Referrer Customers" customer group.</p>
</li>
</ul>
</li>
</ol>
<p>When a customer places an order, the <code>order.placed</code> event is emitted. You can create a subscriber that listens to the event and implements the above logic.</p>
<p>Create a <code>discount.ts</code> file in the <code>src/subscribers</code> directory and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { CustomerGroupService, CustomerService, EventBusService, OrderService } <span class="hljs-keyword">from</span> <span class="hljs-string">"@medusajs/medusa"</span>


<span class="hljs-keyword">type</span> InjectedProperties = {
    eventBusService: EventBusService
    customerGroupService: CustomerGroupService
    customerService: CustomerService
    orderService: OrderService
}


<span class="hljs-keyword">class</span> DiscountSubscriber {
    <span class="hljs-keyword">private</span> customerGroupService: CustomerGroupService
    <span class="hljs-keyword">private</span> customerService: CustomerService
    <span class="hljs-keyword">private</span> orderService: OrderService
    <span class="hljs-keyword">private</span> referredCustomerGroupName: <span class="hljs-built_in">string</span>
    <span class="hljs-keyword">private</span> referrerCustomerGroupName: <span class="hljs-built_in">string</span>

    <span class="hljs-keyword">constructor</span>(<span class="hljs-params">properties: InjectedProperties</span>) {
        <span class="hljs-built_in">this</span>.customerGroupService = properties.customerGroupService;
        <span class="hljs-built_in">this</span>.customerService = properties.customerService;
        <span class="hljs-built_in">this</span>.orderService = properties.orderService;
        <span class="hljs-built_in">this</span>.referredCustomerGroupName = <span class="hljs-string">"Referred Customers"</span>;
        <span class="hljs-built_in">this</span>.referrerCustomerGroupName = <span class="hljs-string">"Referrer Customers"</span>;

        properties.eventBusService.subscribe(<span class="hljs-string">"order.placed"</span>, <span class="hljs-built_in">this</span>.handleDiscounts);
    }

    handleDiscounts = <span class="hljs-keyword">async</span> ({ id }) =&gt; {

        <span class="hljs-comment">// Retrieve the order by id</span>
        <span class="hljs-keyword">const</span> order = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.orderService.retrieve(id, { relations: [<span class="hljs-string">"discounts"</span>] });

        <span class="hljs-comment">// Get the code used by the customer</span>
        <span class="hljs-keyword">const</span> discountCodeUsed = order.discounts &amp;&amp; order.discounts[<span class="hljs-number">0</span>].code;

        <span class="hljs-comment">// Get the customer</span>
        <span class="hljs-keyword">const</span> customer = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerService.retrieve(order.customer_id, { relations: [<span class="hljs-string">"groups"</span>] });

        <span class="hljs-keyword">if</span> (discountCodeUsed === <span class="hljs-string">"NEW10"</span>) {
            <span class="hljs-keyword">const</span> customerGroup = customer.groups.find(<span class="hljs-function"><span class="hljs-params">group</span> =&gt;</span> group.name === <span class="hljs-built_in">this</span>.referredCustomerGroupName);
            <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.removeCustomer(customerGroup.id, [customer.id]);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (discountCodeUsed === <span class="hljs-string">"REFER20"</span>) {
            <span class="hljs-keyword">const</span> totalReferrals = customer.metadata.total_referrals <span class="hljs-keyword">as</span> <span class="hljs-built_in">number</span>;

            <span class="hljs-keyword">if</span> (totalReferrals == <span class="hljs-number">1</span>) {
                <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerService.update(customer.id, {
                    metadata: { <span class="hljs-string">"total_referrals"</span>: <span class="hljs-number">0</span> }
                })
                <span class="hljs-keyword">const</span> customerGroup = customer.groups.find(<span class="hljs-function"><span class="hljs-params">group</span> =&gt;</span> group.name === <span class="hljs-built_in">this</span>.referrerCustomerGroupName);
                <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerGroupService.removeCustomer(customerGroup.id, [customer.id]);
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (totalReferrals &gt; <span class="hljs-number">1</span>) {
                <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.customerService.update(customer.id, {
                    metadata: { <span class="hljs-string">"total_referrals"</span>: totalReferrals - <span class="hljs-number">1</span> }
                })
            }
        }
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> DiscountSubscriber;
</code></pre>
<p>The above code defines a <code>DiscountSubscriber</code> class that listens for the <code>order.placed</code> event through the <code>eventBusService</code> and associates the <code>handleDiscounts</code> method.</p>
<p>In the <code>handleDiscounts</code> method, the code retrieves the order details and extracts the discount code used by the customer. By utilizing the <code>customerService</code>, it retrieves the customer information associated with the order. The code then proceeds to evaluate the discount code used.</p>
<p>If the discount code is identified as "NEW10", it means the customer applied this code. Consequently, the customer is removed from the "Referred Customers" group using the <code>customerGroupService</code>. This step ensures that referred customers no longer remain in the group once they have used the "NEW10" discount.</p>
<p>On the other hand, if the discount code is recognized as "REFER20", the code accesses the customer's metadata to obtain the <code>total_referrals</code> count. If the count is equal to 1, it implies that the customer had only one referral. In this scenario, the code updates the customer's metadata to set the <code>total_referrals</code> count to 0. Additionally, the customer is removed from the "Referrer Customers" group.</p>
<p>However, if the <code>total_referrals</code> count is greater than 1, the code simply decreases the count by 1 in the customer's metadata, representing the utilization of one referral while maintaining the customer's presence in the "Referrer Customers" group.</p>
<p>You'd also want the customers to see their total number of referrals. Open the <code>src/modules/account/components/overview/index.tsx</code> file in the storefront and add the following code:</p>
<pre><code class="lang-typescript">&lt;div className=<span class="hljs-string">"flex flex-col gap-y-4"</span>&gt;
  &lt;div className=<span class="hljs-string">"flex items-center gap-x-2"</span>&gt;
    &lt;h3 className=<span class="hljs-string">"text-large-semi"</span>&gt;Referral Details&lt;/h3&gt;
  &lt;/div&gt;
  &lt;p&gt;
    Your referral code is{<span class="hljs-string">" "</span>}
    &lt;strong&gt;{customer?.metadata[<span class="hljs-string">"referral_code"</span>] || <span class="hljs-string">"loading..."</span>}&lt;/strong&gt;
    . You have referred{<span class="hljs-string">" "</span>}
    &lt;strong&gt;{customer?.metadata[<span class="hljs-string">"total_referrals"</span>] || <span class="hljs-number">0</span>}&lt;/strong&gt;{<span class="hljs-string">" "</span>}
    customers till now.
  &lt;/p&gt;
&lt;/div&gt;
</code></pre>
<h2 id="heading-demo-using-referral-discounts">Demo: Using Referral Discounts</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/Mu8wnt5U8DE">https://youtu.be/Mu8wnt5U8DE</a></div>
<p> </p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this tutorial, you have covered the step-by-step process of implementing a referral system in Medusa. With a functional referral system in place, you can leverage the power of customer referrals to expand your customer base and drive business growth.</p>
<p>This implementation was possible because of Medusa’s composable architecture. You can learn more about Medusa through its <a target="_blank" href="https://docs.medusajs.com/">documentation</a>. Here are some documents that you can start with:</p>
<ul>
<li><p><a target="_blank" href="https://docs.medusajs.com/development/entities/create">Create an entity in Medusa</a></p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/development/services/create-service">Create a service in Medusa</a></p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/development/endpoints/create">Create an API endpoint in Medusa</a></p>
</li>
<li><p><a target="_blank" href="https://docs.medusajs.com/development/events/create-subscriber">Create a subscriber in Medusa</a></p>
</li>
</ul>
<blockquote>
<p>Should you have any issues or questions related to Medusa, then feel free to reach out to the Medusa team via Discord.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[A Beginner's Guide to the JSON Module in Python]]></title><description><![CDATA[JSON (JavaScript Object Notation) is a popular, lightweight data interchange standard. It represents data structures made up of key-value pairs in a straightforward and human-readable manner. JSON has become the industry standard for data interchange...]]></description><link>https://blog.ashutoshkrris.in/a-beginners-guide-to-the-json-module-in-python</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/a-beginners-guide-to-the-json-module-in-python</guid><category><![CDATA[Python]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[json]]></category><category><![CDATA[python beginner]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Tue, 06 Jun 2023 01:31:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685874360522/3c86cde2-f620-4cc1-b500-45de57ade677.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JSON (JavaScript Object Notation) is a popular, lightweight data interchange standard. It represents data structures made up of key-value pairs in a straightforward and human-readable manner. JSON has become the industry standard for data interchange between online services and is widely utilized in modern programming languages, including Python.</p>
<p>JSON data is frequently expressed as nested dictionaries, lists, and scalar values such as texts, numbers, booleans, and null. It is named JSON because it closely mimics the syntax used in JavaScript objects.</p>
<p>In this tutorial, you will explore the JSON module in Python and learn how to effectively work with JSON data.</p>
<h2 id="heading-pythons-built-in-json-module">Python's Built-in JSON Module</h2>
<p>JSON plays an important role in Python programming because it allows efficient data serialization and deserialization. It enables Python programs to effortlessly communicate with web services, exchange data, and store structured information.</p>
<p>Developers can use JSON to seamlessly link their Python programs with a variety of APIs, databases, and external systems that use JSON for data representation.</p>
<blockquote>
<p>If you're looking to learn how to interact with web services using Python, check out <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-interact-with-web-services-using-python">my tutorial on the requests module</a>.</p>
</blockquote>
<p>The built-in JSON module in Python provides a powerful set of methods and classes that make working with JSON data simple. Developers can use it to encode Python objects into JSON strings and decode JSON strings back into Python objects.</p>
<h2 id="heading-storing-json-data-in-a-file">Storing JSON data in a file</h2>
<p>When working with JSON data in Python, it is frequently required to save the data or share it with others. Storing JSON data in a file enables quick retrieval and data persistence.</p>
<p>In this section, you'll learn how to use Python's <code>json.dump()</code> function to save JSON data to a file. This process involves serializing the JSON data and saving it to a file, which can subsequently be read and utilized as needed.</p>
<h3 id="heading-the-jsondump-function">The <code>json.dump()</code> function</h3>
<p>The <code>json.dump()</code> function in Python allows you to store JSON data directly into a file. This function takes two parameters: the data to be serialized and the file object where the data will be written.</p>
<p>To write JSON data to a file, you need to follow a few steps. First, you need to open a file in write mode, specifying the file path. Then, you can use the <code>json.dump()</code> function to serialize the data and write it to the file. Finally, you need to close the file to ensure that all the data is properly saved.</p>
<p>Let's learn how to store data in a file using the horoscope API response as an example.</p>
<p>Assume you have made a GET request to the following URL: <a target="_blank" href="https://horoscope-app-api.vercel.app/api/v1/get-horoscope/daily?sign=capricorn&amp;day=today">https://horoscope-app-api.vercel.app/api/v1/get-horoscope/daily?sign=capricorn&amp;day=today</a>, which provides the daily horoscope for the Capricorn sign.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Make the GET request to the horoscope API</span>
response = requests.get(<span class="hljs-string">"https://horoscope-app-api.vercel.app/api/v1/get-horoscope/daily?sign=capricorn&amp;day=today"</span>)
data = response.json()  <span class="hljs-comment"># Convert the response to JSON</span>

<span class="hljs-comment"># Store the JSON data in a file</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"horoscope_data.json"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> file:
    json.dump(data, file)

print(<span class="hljs-string">"Data stored successfully!"</span>)
</code></pre>
<p>In the code above, you use the <code>requests</code> library to make a GET request to the <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-create-a-horoscope-api-with-beautiful-soup-and-flask">Horoscope API</a>. You then extract the JSON data from the response using the <code>.json()</code> method. Finally, you open a file named <code>horoscope_data.json</code> in write mode using the <code>with</code> statement, and you use <code>json.dump()</code> to store the data in the file.</p>
<blockquote>
<p>Check out <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-know-your-horoscope-using-python">this tutorial</a> to learn how to know your horoscope using Python.</p>
</blockquote>
<p>If you open the <code>horoscope_data.json</code> file, you'll see contents similar to below:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"data"</span>: {
    <span class="hljs-attr">"date"</span>: <span class="hljs-string">"Jun 3, 2023"</span>,
    <span class="hljs-attr">"horoscope_data"</span>: <span class="hljs-string">"The forecast today is stormy. You may have sensed that there was some tension clouding the conversation at home. Resentments were left unsaid and subtle power games were played without resolution. Today, Capricorn, it all becomes too unbearable for you. Regardless of the risks involved, you will take measures to clear things up."</span>
  },
  <span class="hljs-attr">"status"</span>: <span class="hljs-number">200</span>,
  <span class="hljs-attr">"success"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<h2 id="heading-retrieving-data-from-a-json-file">Retrieving data from a JSON file</h2>
<p>It is often required to read data from a JSON file. For example, you can need to read configuration settings from a JSON file. Python's JSON module provides the <code>json.load()</code> function, which allows you to read and deserialize JSON data from a file.</p>
<p>In this section, you will learn how to use the <code>json.load()</code> function to retrieve JSON data from a file and work with it in our Python programs.</p>
<h3 id="heading-the-jsonload-function">The <code>json.load()</code> function</h3>
<p>The <code>json.load()</code> function accepts a file object as an argument and returns deserialized JSON data in the form of Python objects such as dictionaries, lists, strings, numbers, booleans, and null values.</p>
<p>To read JSON data from a file, you need to open the file in read mode, extract the data using the <code>json.load()</code> function, and store it in a variable for further processing. It's important to ensure that the file being read contains valid JSON data; otherwise, it may raise an exception.</p>
<p>Let's see how you can retrieve the data from the previously created <code>horoscope_data.json</code> file:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Retrieve JSON data from the file</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"horoscope_data.json"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    data = json.load(file)

<span class="hljs-comment"># Access and process the retrieved JSON data</span>
date = data[<span class="hljs-string">"data"</span>][<span class="hljs-string">"date"</span>]
horoscope_data = data[<span class="hljs-string">"data"</span>][<span class="hljs-string">"horoscope_data"</span>]

<span class="hljs-comment"># Print the retrieved data</span>
print(<span class="hljs-string">f"Horoscope for date <span class="hljs-subst">{date}</span>: <span class="hljs-subst">{horoscope_data}</span>"</span>)
</code></pre>
<p>In the code above, you open the file <code>horoscope_data.json</code> in read mode using the <code>with</code> statement. You then use the <code>json.load()</code> function to deserialize the JSON data from the file into the data variable. Finally, you access specific fields of the JSON data (e.g., "date" and "horoscope_data") and process them as needed.</p>
<h2 id="heading-formatting-the-json-output">Formatting the JSON Output</h2>
<p>When you read data from a JSON file and print it, the output is displayed as a single line, which may not resemble the structured format of JSON.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Retrieve JSON data from the file</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"horoscope_data.json"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    data = json.load(file)

print(data)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">{<span class="hljs-string">'data'</span>: {<span class="hljs-string">'date'</span>: <span class="hljs-string">'Jun 3, 2023'</span>, <span class="hljs-string">'horoscope_data'</span>: <span class="hljs-string">'The forecast today is stormy. You may have sensed that there was some tension clouding the conversation at home. Resentments were left unsaid and subtle power games were played without resolution. Today, Capricorn, it all becomes too unbearable for you. Regardless of the risks involved, you will take measures to clear things up.'</span>}, <span class="hljs-string">'status'</span>: 200, <span class="hljs-string">'success'</span>: True}
</code></pre>
<h3 id="heading-the-jsondumps-function">The <code>json.dumps()</code> function</h3>
<p>The JSON module provides you with a <code>json.dumps()</code> function to serialize Python objects into a JSON formatted string. It provides various options for customization, including formatting the output to make it more human-readable.</p>
<p>The <code>json.dumps()</code> function provides several <a target="_blank" href="https://docs.python.org/3/library/json.html#json.dumps">options</a> to customize the output. The most commonly used is the <code>indent</code> which allows you to specify the number of spaces used for indentation.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Retrieve JSON data from the file</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"horoscope_data.json"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    data = json.load(file)

<span class="hljs-comment"># Format the data</span>
formatted_data = json.dumps(data, indent=<span class="hljs-number">2</span>)

print(formatted_data)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"date"</span>: <span class="hljs-string">"Jun 3, 2023"</span>,
    <span class="hljs-string">"horoscope_data"</span>: <span class="hljs-string">"The forecast today is stormy. You may have sensed that there was some tension clouding the conversation at home. Resentments were left unsaid and subtle power games were played without resolution. Today, Capricorn, it all becomes too unbearable for you. Regardless of the risks involved, you will take measures to clear things up."</span>
  },
  <span class="hljs-string">"status"</span>: 200,
  <span class="hljs-string">"success"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<p>As you can see, the JSON data is now formatted with proper indentation enhancing its readability. This technique can be applied to any JSON data, allowing you to present JSON output in a more organized and visually appealing way.</p>
<h2 id="heading-the-jsontool-command-line-tool">The <code>json.tool</code> command-line tool</h2>
<p>Python's JSON module provides a convenient command-line tool called <code>json.tool</code> that allows you to format and pretty-print JSON data directly from the command line. It is a useful utility for quickly visualizing the structure and contents of JSON data in a more readable and organized format.</p>
<p>To use <code>json.tool</code>, you can execute the following command in your command-line interface:</p>
<pre><code class="lang-bash">python -m json.tool &lt;input_file&gt; &lt;output_file&gt;
</code></pre>
<p>where:</p>
<ul>
<li><p><code>python -m json.tool</code> invokes the <code>json.tool</code> module using the Python interpreter.</p>
</li>
<li><p><code>&lt;input_file&gt;</code> represents the path to the JSON file you want to format.</p>
</li>
<li><p><code>&lt;output_file&gt;</code> is an optional argument that specifies the file to which you want to save the formatted JSON output. If not provided, the formatted output will be displayed on the console.</p>
</li>
</ul>
<p>Let's say you have a <code>horoscope_data.json</code> file with the following contents:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"data"</span>: {
    <span class="hljs-attr">"date"</span>: <span class="hljs-string">"Jun 3, 2023"</span>,
    <span class="hljs-attr">"horoscope_data"</span>: <span class="hljs-string">"The forecast today is stormy. You may have sensed that there was some tension clouding the conversation at home. Resentments were left unsaid and subtle power games were played without resolution. Today, Capricorn, it all becomes too unbearable for you. Regardless of the risks involved, you will take measures to clear things up."</span>
  },
  <span class="hljs-attr">"status"</span>: <span class="hljs-number">200</span>,
  <span class="hljs-attr">"success"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<blockquote>
<p>Notice that the above JSON file has an indentation of two spaces.</p>
</blockquote>
<p>To pretty-print this JSON file using <code>json.tool</code>, you can execute the following command:</p>
<pre><code class="lang-bash">python -m json.tool horoscope_data.json
</code></pre>
<p>The output will be:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"data"</span>: {
        <span class="hljs-attr">"date"</span>: <span class="hljs-string">"Jun 3, 2023"</span>,
        <span class="hljs-attr">"horoscope_data"</span>: <span class="hljs-string">"The forecast today is stormy. You may have sensed that there was some tension clouding the conversation at home. Resentments were left unsaid and subtle power games were played without resolution. Today, Capricorn, it all becomes too unbearable for you. Regardless of the risks involved, you will take measures to clear things up."</span>
    },
    <span class="hljs-attr">"status"</span>: <span class="hljs-number">200</span>,
    <span class="hljs-attr">"success"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<p>As seen in the example, executing the <code>json.tool</code> module with the input file path formats the JSON data and displays the formatted output on the console.</p>
<p>You can also redirect the formatted output to an output file by specifying the output file name as the second argument:</p>
<pre><code class="lang-bash">python -m json.tool horoscope_data.json formatted_data.json
</code></pre>
<p>This command formats the JSON data from <code>horoscope_data.json</code> and saves the formatted output to <code>formatted_data.json</code>.</p>
<h2 id="heading-json-encoding-custom-objects">JSON Encoding Custom Objects</h2>
<p>The JSON module in Python allows you to encode and decode custom objects by using JSON encoder and decoder classes. You can define custom serialization and deserialization logic for your objects using these classes.</p>
<p><code>JSONEncoder</code> class allows you to customize the encoding process. To define how your custom object should be encoded into JSON format, you can extend the <code>JSONEncoder</code> and change its <code>default</code> method.</p>
<p>Here's an example of how you can extend the <code>JSONEncoder</code> class and customize the encoding process for a custom object:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, name, age</span>):</span>
        self.name = name
        self.age = age


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonEncoder</span>(<span class="hljs-params">json.JSONEncoder</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">default</span>(<span class="hljs-params">self, obj</span>):</span>
        <span class="hljs-keyword">if</span> isinstance(obj, Person):
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"name"</span>: obj.name, <span class="hljs-string">"age"</span>: obj.age}
        <span class="hljs-keyword">return</span> super().default(obj)


<span class="hljs-comment"># Create a custom object</span>
person = Person(<span class="hljs-string">"Ashutosh Krishna"</span>, <span class="hljs-number">23</span>)

<span class="hljs-comment"># Encode the custom object using the custom encoder</span>
json_str = json.dumps(person, cls=PersonEncoder)

<span class="hljs-comment"># Print the encoded JSON string</span>
print(json_str)
</code></pre>
<p>In this example, you define a custom class <code>Person</code> with <code>name</code> and <code>age</code> attributes. You then create a subclass of <code>JSONEncoder</code> called <code>PersonEncoder</code> and override its <code>default</code> method. Within the <code>default</code> method, you check if the object being encoded is an instance of <code>Person</code>. If it is, you provide a JSON-serializable representation of the object by returning a dictionary containing the <code>name</code> and <code>age</code> attributes. If the object is not of type <code>Person</code>, you call the <code>default</code> method of the superclass to handle other types.</p>
<p>By using <code>json.dumps</code> and specifying the <code>cls</code> parameter as your custom encoder class <code>PersonEncoder</code>, you can encode the <code>person</code> object into a JSON string. The output will be:</p>
<pre><code class="lang-bash">{<span class="hljs-string">"name"</span>: <span class="hljs-string">"Ashutosh Krishna"</span>, <span class="hljs-string">"age"</span>: 23}
</code></pre>
<p>Similarly, you can specify custom decoding logic in the JSON decoder class, <code>JSONDecoder</code>. To define how JSON data should be decoded into your custom object, extend the <code>JSONDecoder</code> and override its <code>object_hook</code> function.</p>
<h2 id="heading-how-to-create-json-from-python-dictionary">How to create JSON from Python Dictionary</h2>
<p>You can use the <code>json.dumps()</code> function provided by the JSON module to create JSON from a <a target="_blank" href="https://blog.ashutoshkrris.in/everything-you-need-to-know-about-python-dictionaries">Python dictionary</a>. This function takes a Python object, typically a dictionary, and converts it into a JSON string representation.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-comment"># Python dictionary</span>
data = {
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"Ashutosh Krishna"</span>,
    <span class="hljs-string">"age"</span>: <span class="hljs-number">23</span>,
    <span class="hljs-string">"email"</span>: <span class="hljs-string">"ashutosh@example.com"</span>
}

<span class="hljs-comment"># Convert dictionary to JSON string</span>
json_str = json.dumps(data)

<span class="hljs-comment"># Print the JSON string</span>
print(json_str)
</code></pre>
<p>In this example, you have a Python dictionary <code>data</code> representing some data. By calling <code>json.dumps(data)</code>, you convert the dictionary into a JSON string. The output will be:</p>
<pre><code class="lang-bash">{<span class="hljs-string">"name"</span>: <span class="hljs-string">"Ashutosh Krishna"</span>, <span class="hljs-string">"age"</span>: 23, <span class="hljs-string">"email"</span>: <span class="hljs-string">"ashutosh@example.com"</span>}
</code></pre>
<h2 id="heading-how-to-create-a-python-dictionary-from-json">How to create a Python dictionary from JSON</h2>
<p>To create a Python dictionary from JSON data, you can use the <code>json.loads()</code> function provided by the JSON module. This function takes a JSON string and converts it into a corresponding Python object, typically a dictionary.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> json

<span class="hljs-comment"># JSON string</span>
json_str = <span class="hljs-string">'{"name": "Ashutosh Krishna", "age": 23, "email": "ashutosh@example.com"}'</span>

<span class="hljs-comment"># Convert JSON string to Python dictionary</span>
data = json.loads(json_str)

<span class="hljs-comment"># Access the dictionary values</span>
print(data[<span class="hljs-string">"name"</span>])
print(data[<span class="hljs-string">"age"</span>])
print(data[<span class="hljs-string">"email"</span>])
</code></pre>
<p>In this example, you have a JSON string <code>json_str</code> representing some data. By calling <code>json.loads(json_str)</code>, you convert the JSON string into a Python dictionary. You can then access the values in the dictionary using their respective keys.</p>
<p>The output will be:</p>
<pre><code class="lang-bash">Ashutosh Krishna
23
ashutosh@example.com
</code></pre>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Understanding the Python JSON module is necessary for working with JSON data because it is widely used for data exchange and storage in a variety of applications. You can efficiently handle JSON data, interface with APIs, and deal with configuration files if you learn the JSON module.</p>
<div class="hn-embed-widget" id="buymeacoffee"></div>]]></content:encoded></item><item><title><![CDATA[How to Add Newsletter Subscription in Medusa with Mailchimp]]></title><description><![CDATA[Medusa is an open source, composable commerce platform designed for developers. With its flexible architecture, Medusa enables users to create custom commerce solutions that meet their specific needs. It provides modular commerce infrastructure that ...]]></description><link>https://blog.ashutoshkrris.in/how-to-add-newsletter-subscription-in-medusa-with-mailchimp</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-add-newsletter-subscription-in-medusa-with-mailchimp</guid><category><![CDATA[medusa]]></category><category><![CDATA[mailchimp]]></category><category><![CDATA[newsletter]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Wed, 10 May 2023 19:02:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683745264090/0d8aed9c-c610-474a-b050-aea6eb461343.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Medusa is an open source, composable commerce platform designed for developers. With its flexible architecture, Medusa enables users to create custom commerce solutions that meet their specific needs. It provides modular commerce infrastructure that makes custom development processes easier for developers. Medusa leverages cutting-edge infrastructure technologies such as serverless and edge workers to ensure scalability, reliability, and performance.</p>
<p>Mailchimp, on the other hand, is an all-in-one marketing platform that enables users to create and send newsletters, automated emails, and targeted ad campaigns. It also allows users to manage their email lists, track their email campaign performance, and access a range of marketing tools.</p>
<p>In this tutorial, you will learn how to add newsletter subscriptions to your Medusa store using Mailchimp, allowing visitors to sign up for email updates and newsletters. This will enable you to stay in touch with your customers, promote your products and services, and ultimately drive sales. Whether you're running an e-commerce store or a business website, adding newsletter subscriptions is a valuable tool for building a loyal customer base and driving growth.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you get started with the tutorial, make sure that you have the following prerequisites installed on your system:</p>
<ol>
<li><p>Node: Medusa is built on Node.js, so you'll need to have <a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment#nodejs">Node.js(V16 or later)</a> installed to run Medusa.</p>
</li>
<li><p>Git: Medusa uses <a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment/#git">Git</a> behind the scenes when you create a new project so you'll have to install it on your computer to get started.</p>
</li>
<li><p>Medusa-CLI: The package provides you instant access to commands that help you manage and run your Medusa project.</p>
<p> You can install Medusa’s CLI with the following command:</p>
<pre><code class="lang-bash"> npm install @medusajs/medusa-cli -g
</code></pre>
</li>
</ol>
<p>You can find the code for the tutorial in this <a target="_blank" href="https://github.com/ashutoshkrris/medusa-newsletter-mailchimp">repository</a>.</p>
<h2 id="heading-setting-up-mailchimp">Setting up Mailchimp</h2>
<p>To get started with adding newsletter subscriptions to your Medusa store using Mailchimp, you'll need to set up a Mailchimp account and obtain your API key. Follow the steps below to complete this process:</p>
<ol>
<li><p>If you haven't already, go to the <a target="_blank" href="https://mailchimp.com/">Mailchimp website</a> and <a target="_blank" href="https://login.mailchimp.com/signup/">sign up for an account</a>.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683285443240/ec40e45d-3a02-446e-8120-98c507c3992c.png" alt="Sign up for Mailchimp" class="image--center mx-auto" /></p>
</li>
<li><p>Once you've signed up, create a new audience (i.e. mailing list) in Mailchimp. This is where your subscriber information will be stored.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683291294006/32f6e49d-121b-4bc2-811c-443728f02f61.gif" alt="Creating Audience" class="image--center mx-auto" /></p>
<p> Make sure you take note of your <strong>Audience ID</strong> shown at the end of the above demo.</p>
</li>
<li><p>Next, you'll need to obtain your API key. Go to your Mailchimp account profile, click on the "Extras" drop-down menu, and select "API keys." From there, you can create a new API key.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683291863140/87140cc9-24d0-4283-bfd0-7d5bcadbc3c8.gif" alt="Creating API Key" class="image--center mx-auto" /></p>
<p> Make sure you take note of the newly generated API Key.</p>
</li>
</ol>
<p>Once you've completed these steps, you'll be ready to integrate Mailchimp with your Medusa store and start adding newsletter subscriptions.</p>
<h2 id="heading-setting-up-medusa-backend">Setting up Medusa Backend</h2>
<p>The Medusa Backend contains all the store's logic and data. The other two components, Medusa Admin and Storefront use the REST APIs exposed by the backend server to retrieve, create and modify data.</p>
<p>In this section, you’ll set up your Medusa backend. Create a new Medusa store called <code>my-medusa-store</code> and seed the test data using the following command:</p>
<pre><code class="lang-bash">medusa new my-medusa-store --seed
</code></pre>
<p>Then, start your Medusa server using the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-medusa-store
medusa develop
</code></pre>
<p>The above two steps take a couple of minutes to set up and run your server on port 9000. You can test your server by going to <a target="_blank" href="http://localhost:9000/store/products">http://localhost:9000/store/products</a> on your browser or by running the following command:</p>
<pre><code class="lang-bash">curl localhost:9000/store/products
</code></pre>
<p>If your server is successfully set up, you will see a list of products and other details.</p>
<h2 id="heading-medusa-mailchimp-plugin">Medusa Mailchimp Plugin</h2>
<p><a target="_blank" href="https://medusajs.com/plugins/">Plugins</a> are add-ons that extend the functionality of Medusa. They are designed to work seamlessly with Medusa's modular architecture, allowing users to easily add new features to their commerce setup. The <a target="_blank" href="https://medusajs.com/plugins/medusa-plugin-mailchimp/">Medusa Mailchimp</a> plugin is one such plugin that enables you to add newsletter subscriptions to your Medusa store using Mailchimp.</p>
<p>To install the Medusa Mailchimp plugin, follow these steps:</p>
<ol>
<li><p>Navigate to the directory of your Medusa backend and run the following command to install the Mailchimp plugin:</p>
<pre><code class="lang-bash"> npm install medusa-plugin-mailchimp
</code></pre>
</li>
<li><p>Once the installation is complete, add the plugin to your Medusa project's configuration file (<code>medusa-config.js</code>):</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> plugins = [
   <span class="hljs-comment">// ...,</span>
   {
     <span class="hljs-attr">resolve</span>: <span class="hljs-string">`medusa-plugin-mailchimp`</span>,
     <span class="hljs-attr">options</span>: {
       <span class="hljs-attr">api_key</span>: process.env.MAILCHIMP_API_KEY,
       <span class="hljs-attr">newsletter_list_id</span>: 
         process.env.MAILCHIMP_NEWSLETTER_LIST_ID,
     },
   },
 ]
</code></pre>
</li>
<li><p>If you noticed above, you're using two environment variables - <code>MAILCHIMP_API_KEY</code> and <code>MAILCHIMP_NEWSLETTER_LIST_ID</code>. Thus, next you need to add these two environment variables to the <code>.env</code> file:</p>
<pre><code class="lang-javascript"> MAILCHIMP_API_KEY=&lt;YOUR_API_KEY&gt;
 MAILCHIMP_NEWSLETTER_LIST_ID=&lt;YOUR_NEWSLETTER_LIST_ID&gt;
</code></pre>
<p> Replace <code>&lt;YOUR_API_KEY&gt;</code> with your Mailchimp API key, which you created in Mailchimp earlier, and <code>&lt;YOUR_NEWSLETTER_LIST_ID&gt;</code> with your Audience ID. I hope you had noted them.</p>
</li>
</ol>
<p>Once you've completed these steps, the Medusa Mailchimp plugin will be installed and configured to work with your Mailchimp account.</p>
<h3 id="heading-test-it-out">Test it Out</h3>
<p>The Medusa Mailchimp plugin adds a new POST endpoint to your Medusa server at <code>/mailchimp/subscribe</code>. To subscribe to your Mailchimp audience, users need to include an <code>email</code> field in the body of their request. Additionally, users can optionally include a <code>data</code> object in the request body to send any additional data they want to include in the subscription request.</p>
<p>Make sure your backend server is running to test things out.</p>
<p>You can test the <code>/mailchimp/subscribe</code> endpoint by sending a POST request with a JSON body that includes an email address. You can use the following <code>curl</code> command to send a POST request:</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'{"email": "example@gmail.com"}'</span> http://localhost:9000/mailchimp/subscribe
</code></pre>
<p>Running this command will send a POST request to the <code>/mailchimp/subscribe</code> endpoint with a JSON body that includes the email address <code>example@gmail.com</code>.</p>
<blockquote>
<p>Note: You can also use tools such as Postman and Talend API Tester to make requests.</p>
</blockquote>
<p>If the subscription is successful, a <code>200</code> response code will be returned with <code>OK</code> message. If you check your Mailchimp dashboard, you should find the email added to your Audience list.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683295134511/2ca64a30-d317-40dd-bf87-b8cba5c4e235.png" alt class="image--center mx-auto" /></p>
<p>You can also send additional data with the request as shown below:</p>
<pre><code class="lang-bash">curl -X POST -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'{"email": "demo@gmail.com", "data": {"tags": ["demouser"]}}'</span> http://localhost:9000/mailchimp/subscribe
</code></pre>
<p>You can see <code>demouser</code> in the tags of the subscribed email.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683295841195/fa9644b7-b0b0-434f-a32e-4e67e48a511d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-setting-up-medusa-storefront">Setting up Medusa Storefront</h2>
<p>You'll add the newsletter subscription form to your Medusa storefront. Storefront is the frontend or the main presentation layer of your ecommerce store. It is the storefront where your customers can view and purchase your products.</p>
<p>In this section, you'll set up your Next.js Storefront using the starter template provided by Medusa.</p>
<p>Create a new Medusa storefront by running the following command:</p>
<pre><code class="lang-bash">npx create-next-app -e https://github.com/medusajs/nextjs-starter-medusa my-medusa-storefront
</code></pre>
<p>Next, navigate to the newly created <code>my-medusa-storefront</code> directory and rename the template environment variable file to use environment variables in development:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-medusa-storefront
mv .env.template .env.local
</code></pre>
<p>Finally, make sure the Medusa server is running, then run the storefront:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Your Next.js storefront is now running at http://localhost:8000.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683296826016/50dcf56e-47a9-4c61-85f1-31d250bc5a2a.png" alt="Medusa Storefront" class="image--center mx-auto" /></p>
<h2 id="heading-adding-a-newsletter-subscription-form">Adding a Newsletter Subscription Form</h2>
<p>In this section, you will add a newsletter subscription form to your Medusa storefront. The form will have just an input field for the users to enter their email addresses and a button to subscribe.</p>
<p>If you take a look at the footer of the application, it looks a bit empty. You can add the form here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683297889706/e94c8e22-3c2f-4e8e-b55a-6a20947a8755.png" alt="Storefront Footer" class="image--center mx-auto" /></p>
<h3 id="heading-create-a-new-component">Create a New Component</h3>
<p>To add the newsletter subscription form, create a new file named <code>newsletter.tsx</code> inside the <code>src/modules/layout/components/footer-nav</code> folder where the footer component code is located.</p>
<p>Create a new <code>NewsletterForm</code> component in the file as:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<p>Next, create a form with an input field for the email and a button to subscribe.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
          <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
          <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"border-gray-300 focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50 rounded-md shadow-sm w-full px-4"</span>
          <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"example@gmail.com"</span>
        /&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"ml-2 bg-gray-800 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded"</span>
        &gt;</span>
          Subscribe
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<p>In the above code, you returned a form from the <code>NewsletterForm</code> component. The form consists of an email input field and a subscribe button. The email input field is of type "email" with a placeholder text "<a target="_blank" href="mailto:example@gmail.com"><strong>example@gmail.com</strong></a>". It has a gray border and rounded corners. On focus, the border becomes blue with a light blue ring around it.</p>
<p>The subscribe button is styled with a gray background, white text, and rounded corners. On hover, the background color becomes darker gray.</p>
<p>This component does not currently have any functionality associated with the subscribe button. In a later section, you'll connect it to the backend server to handle the subscription process when the button is clicked.</p>
<h3 id="heading-use-the-newsletterform-component">Use the NewsletterForm component</h3>
<p>Now that you've created the <code>NewsletterForm</code> component, you are ready to use it. Open the <code>footer-nav/index.tsx</code> file and import the component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> NewsletterForm <span class="hljs-keyword">from</span> <span class="hljs-string">"./newsletter"</span>
</code></pre>
<p>Next, use the component as below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> FooterNav = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { collections } = useCollections()
    <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"content-container flex flex-col gap-y-8 pt-16 pb-8"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col gap-y-6 xsmall:flex-row items-start justify-between"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl-semi uppercase"</span>&gt;</span>Acme<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex gap-x-4"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">NewsletterForm</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        ...
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> FooterNav
</code></pre>
<p>Now, if you take a look at your footer, you'll have a newsletter form created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683299600557/3ae6b275-1236-4305-8998-28517fb22688.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-adding-button-functionality">Adding Button Functionality</h3>
<p>After creating the newsletter subscription form, the next step is to add the subscription functionality to the button. To do this, you need to create a function that will send the email address to your server when the user clicks the "Subscribe" button.</p>
<p>First, you need to import the <code>useState</code> hook from React in your <code>NewsletterForm</code> component. You will use this hook to manage the state of the email input field.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
</code></pre>
<p>Next, you will initialize the state of the email input field to an empty string using the <code>useState</code> hook.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">""</span>)

  <span class="hljs-keyword">return</span> (
    ...
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<p>Then, you need to add an <code>onChange</code> event handler to the email input field that will update the email state whenever the user types in a new email address.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span>
  <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
  <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
  <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
  <span class="hljs-attr">className</span>=<span class="hljs-string">"border-gray-300 focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50 rounded-md shadow-sm w-full px-4"</span>
  <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"example@gmail.com"</span>
  <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span>
  <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)}
/&gt;
</code></pre>
<p>Now, you will add the subscription functionality to the button. When the user clicks the "Subscribe" button, the form gets submitted. You'll create a function that will be called when the form is submitted.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> subscribe = <span class="hljs-function">(<span class="hljs-params">e: React.FormEvent&lt;HTMLFormElement&gt;</span>) =&gt;</span> {
  e.preventDefault()
  <span class="hljs-keyword">if</span> (!email) {
    <span class="hljs-keyword">return</span>
  }

  fetch(<span class="hljs-string">"http://localhost:9000/mailchimp/subscribe"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ email }),
  })
    .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.json())
    .then(<span class="hljs-function">() =&gt;</span> {
      alert(<span class="hljs-string">"Subscribed successfully!"</span>)
      setEmail(<span class="hljs-string">""</span>)
    })
    .catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.error(e)
      alert(<span class="hljs-string">"An error occurred"</span>)
    })
}
</code></pre>
<p>The <code>subscribe</code> function takes in a <code>React.FormEvent&lt;HTMLFormElement&gt;</code> event as an argument. This event is triggered when the form is submitted. Inside the function, the first thing you do is prevent the default behavior of the form as you don't want the page to reload or redirect. Next, it checks if the <code>email</code> variable has a value. If it doesn't, the function returns and doesn't proceed further.</p>
<p>Then, it uses <code>fetch</code> to make a POST request to the specified URL <a target="_blank" href="http://localhost:9000/mailchimp/subscribe"><code>http://localhost:9000/mailchimp/subscribe</code></a>. The <code>method</code> property of the <code>fetch</code> call is set to <code>"POST"</code>, and the <code>"Content-Type"</code> header is set to <code>"application/json"</code>. The <code>body</code> property of the <code>fetch</code> call is set to a JSON string that contains an object with a single key-value pair: <code>{ email: email }</code>. This is the email that the user has entered into the form.</p>
<p>Once the request is made, the response is received and converted to JSON format by calling <code>response.json()</code>. The function then displays a success message using <code>alert("Subscribed successfully!")</code> and clears the <code>email</code> variable by calling <code>setEmail("")</code>.</p>
<p>If there is an error, it is caught and logged to the console using <code>console.error(e)</code>, and an error message is displayed to the user using <code>alert("An error occurred")</code>.</p>
<p>The form now has an <code>onSubmit</code> attribute that is set to the <code>subscribe</code> function. When the form is submitted by clicking the Subscribe button, the <code>subscribe</code> function is called.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">""</span>)

  <span class="hljs-keyword">const</span> subscribe = <span class="hljs-function">(<span class="hljs-params">e: React.FormEvent&lt;HTMLFormElement&gt;</span>) =&gt;</span> {
    ...
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{subscribe}</span>&gt;</span>
      ...
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<p>Now, if you test the application, it should be working.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683304680365/dcae6ade-b92d-40bb-ad98-82a5cba23a24.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-improving-the-user-experience">Improving the User Experience</h2>
<p>While the basic functionality of the subscription form is in place, the user is unaware of the background process when clicking the subscribe button. To improve the user experience, you can include a loader to indicate that the form is processing. Additionally, the current alert box for success or error notifications can be replaced with a message that appears below the input field, providing a cleaner and more visually appealing interface. In this section, you'll add these improvements.</p>
<h3 id="heading-adding-a-loader">Adding a Loader</h3>
<p>To add a loader to the existing <code>NewsletterForm</code> component, you can first import the necessary components and hooks from the <code>@headlessui/react</code> library and a <code>Spinner</code> component from your project's modules.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Dialog, Transition } <span class="hljs-keyword">from</span> <span class="hljs-string">"@headlessui/react"</span>
<span class="hljs-keyword">import</span> Spinner <span class="hljs-keyword">from</span> <span class="hljs-string">"@modules/common/icons/spinner"</span>
</code></pre>
<p>Next, you can create a new state variable <code>isLoading</code> using the <code>useState</code> hook and initialize it to <code>false</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  ...
  const [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>)

  ...
}
</code></pre>
<p>You can then add a <code>Transition</code> component and conditionally render a <code>Dialog</code> component with a spinner inside it when <code>isLoading</code> is true.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { Dialog, Transition } <span class="hljs-keyword">from</span> <span class="hljs-string">"@headlessui/react"</span>
<span class="hljs-keyword">import</span> Spinner <span class="hljs-keyword">from</span> <span class="hljs-string">"@modules/common/icons/spinner"</span>

<span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  ...

  return (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{subscribe}</span>&gt;</span>
        ...
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

      {isLoading &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">Transition</span> <span class="hljs-attr">show</span>=<span class="hljs-string">{isLoading}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Dialog</span>
            <span class="hljs-attr">onClose</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsLoading(false)}
            className="relative z-[100]"
          &gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Transition.Child</span>
              <span class="hljs-attr">enter</span>=<span class="hljs-string">"ease-out duration-500"</span>
              <span class="hljs-attr">enterFrom</span>=<span class="hljs-string">"opacity-0"</span>
              <span class="hljs-attr">enterTo</span>=<span class="hljs-string">"opacity-100"</span>
              <span class="hljs-attr">leave</span>=<span class="hljs-string">"ease-in duration-500"</span>
              <span class="hljs-attr">leaveFrom</span>=<span class="hljs-string">"opacity-100"</span>
              <span class="hljs-attr">leaveTo</span>=<span class="hljs-string">"opacity-0"</span>
            &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"fixed inset-0 bg-white bg-opacity-50 flex items-center justify-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Spinner</span> <span class="hljs-attr">size</span>=<span class="hljs-string">{24}</span> /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Transition.Child</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Dialog</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Transition</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<p>To show the loader during form submission, you can set <code>isLoading</code> to true just before making the <code>fetch</code> call and set it back to false in a <code>finally()</code> block.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> subscribe = <span class="hljs-function">(<span class="hljs-params">e: React.FormEvent&lt;HTMLFormElement&gt;</span>) =&gt;</span> {
    e.preventDefault()
    <span class="hljs-keyword">if</span> (!email) {
      <span class="hljs-keyword">return</span>
    }

    setIsLoading(<span class="hljs-literal">true</span>) <span class="hljs-comment">// show loader</span>

    fetch(<span class="hljs-string">"http://localhost:9000/mailchimp/subscribe"</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ email }),
    })
      .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!response.ok) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(response.statusText)
        }
        <span class="hljs-keyword">return</span> response.text()
      })
      .then(<span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (text === <span class="hljs-string">"OK"</span>) {
          alert(<span class="hljs-string">"Subscribed successfully!"</span>)
          setEmail(<span class="hljs-string">""</span>)
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unexpected response from server"</span>)
        }
        setEmail(<span class="hljs-string">""</span>)
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.error(e)
        alert(<span class="hljs-string">"An error occurred"</span>)
      })
      .finally(<span class="hljs-function">() =&gt;</span> {
        setIsLoading(<span class="hljs-literal">false</span>) <span class="hljs-comment">// hide loader</span>
      })
  }
</code></pre>
<p>Alternatively, you could have set the loader to false in the <code>.then()</code> and <code>.catch()</code> blocks also.</p>
<p>With the addition of the loader, the NewsletterForm component will now display a spinner to indicate that the form is being submitted. This will help users understand that something is happening in the background and prevent them from submitting the form multiple times. The spinner will be shown until the request is completed, whether it was successful or not, and will be hidden once the process is complete. This improved user experience will make the form more user-friendly and professional-looking.</p>
<h3 id="heading-adding-a-message">Adding a Message</h3>
<p>Next, you need to replace the alert boxes with appropriate messages. To do so, you need to add a state variable to keep track of the message to be displayed. Create a new state variable <code>message</code> using the <code>useState</code> hook and initialize it to <code>null</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [message, setMessage] = useState&lt;Message | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>)
</code></pre>
<p>The <code>Message</code> here is a custom interface that defines the shape of the data that you want to store in the <code>message</code> state variable. You need this interface to enforce a specific structure on the data that you want to store in the <code>message</code> state variable, which helps you avoid errors when accessing or manipulating the data.</p>
<p>You can create the <code>Message</code> interface before the <code>NewsletterForm</code> component as:</p>
<pre><code class="lang-javascript">interface Message {
  <span class="hljs-attr">type</span>: string
  <span class="hljs-attr">description</span>: string
}

<span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  ...
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<p>The <code>Message</code> that has two properties: <code>type</code> and <code>description</code>, both of which are strings.</p>
<p>Next, you need to update the <code>subscribe</code> function to set the message based on the response from the server.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> subscribe = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  e.preventDefault()
  <span class="hljs-keyword">if</span> (!email) {
    setMessage({
      <span class="hljs-attr">type</span>: <span class="hljs-string">"error"</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">"Email cannot be empty!"</span>,
    })
    <span class="hljs-keyword">return</span>
  }
  setIsLoading(<span class="hljs-literal">true</span>)

  fetch(<span class="hljs-string">"http://localhost:9000/mailchimp/subscribe"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ email }),
  })
    .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (!response.ok) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(response.statusText)
      }
      <span class="hljs-keyword">return</span> response.text()
    })
    .then(<span class="hljs-function">(<span class="hljs-params">text</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (text === <span class="hljs-string">"OK"</span>) {
        setMessage({
          <span class="hljs-attr">type</span>: <span class="hljs-string">"success"</span>,
          <span class="hljs-attr">description</span>: <span class="hljs-string">"Subscribed successfully!"</span>,
        })
        setEmail(<span class="hljs-string">""</span>)
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unexpected response from server"</span>)
      }
      setEmail(<span class="hljs-string">""</span>)
    })
    .catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
      <span class="hljs-built_in">console</span>.error(e)
      setMessage({
        <span class="hljs-attr">type</span>: <span class="hljs-string">"error"</span>,
        <span class="hljs-attr">description</span>: <span class="hljs-string">"An error occurred"</span>,
      })
    })
    .finally(<span class="hljs-function">() =&gt;</span> {
      setIsLoading(<span class="hljs-literal">false</span>)
    })
}
</code></pre>
<p>When the user clicks the subscribe button, the function checks if the email field is empty. If it is, it sets a message with the type <code>error</code> and description "Email cannot be empty".</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (!email) {
  setMessage({
    <span class="hljs-attr">type</span>: <span class="hljs-string">"error"</span>,
    <span class="hljs-attr">description</span>: <span class="hljs-string">"Email cannot be empty!"</span>,
  })
  <span class="hljs-keyword">return</span>
}
</code></pre>
<p>When the response comes back, the function checks whether the response is OK. If it is, it sets a message with the type <code>success</code> and description "Subscribed successfully!" and clears the email field.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (text === <span class="hljs-string">"OK"</span>) {
  setMessage({
    <span class="hljs-attr">type</span>: <span class="hljs-string">"success"</span>,
    <span class="hljs-attr">description</span>: <span class="hljs-string">"Subscribed successfully!"</span>,
  })
  setEmail(<span class="hljs-string">""</span>)
}
</code></pre>
<p>If the response is not OK, it sets a message with the type <code>error</code> and description "An error occurred". Finally, the <code>isLoading</code> state is set to <code>false</code>.</p>
<pre><code class="lang-javascript">.catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(e)
  setMessage({
    <span class="hljs-attr">type</span>: <span class="hljs-string">"error"</span>,
    <span class="hljs-attr">description</span>: <span class="hljs-string">"An error occurred"</span>,
  })
})
</code></pre>
<p>Moreover, it is important to ensure that if a message is already visible and the user starts typing again, the message should be set to <code>null</code>.</p>
<pre><code class="lang-javascript">onChange={<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
  setEmail(e.target.value)
  setMessage(<span class="hljs-literal">null</span>)
}}
</code></pre>
<p>Now that you have the message state set up, you can conditionally display the message:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { Dialog, Transition } <span class="hljs-keyword">from</span> <span class="hljs-string">"@headlessui/react"</span>
<span class="hljs-keyword">import</span> Spinner <span class="hljs-keyword">from</span> <span class="hljs-string">"@modules/common/icons/spinner"</span>

interface Message {
  <span class="hljs-attr">type</span>: string
  <span class="hljs-attr">description</span>: string
}

<span class="hljs-keyword">const</span> NewsletterForm = <span class="hljs-function">() =&gt;</span> {
  ...

  return (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{subscribe}</span>&gt;</span>
        ...
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

      {isLoading &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">Transition</span> <span class="hljs-attr">show</span>=<span class="hljs-string">{isLoading}</span>&gt;</span>
          ...
        <span class="hljs-tag">&lt;/<span class="hljs-name">Transition</span>&gt;</span>
      )}

      {message &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">mt-2</span> <span class="hljs-attr">text-sm</span> <span class="hljs-attr">font-medium</span> ${
            <span class="hljs-attr">message.type</span> === <span class="hljs-string">"success"</span> ? "<span class="hljs-attr">text-green-600</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">text-red-600</span>"
          }`}
        &gt;</span>
          {message.description}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> NewsletterForm
</code></pre>
<h2 id="heading-demo">Demo</h2>
<p>Now that you have everything set up successfully, it's time to see the final demo of the application you've built.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683307505182/3d2fbb49-3ae3-48e1-8d0c-e72413747d09.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned the importance of adding a newsletter service to increase customer engagement and sales. You then went through the process of adding a newsletter subscription service to your Medusa store.</p>
<p>This implementation was possible because of Medusa’s composable architecture. You can learn more about Medusa through its <a target="_blank" href="https://docs.medusajs.com/">documentation</a>.</p>
]]></content:encoded></item><item><title><![CDATA[A Beginner's Guide to Strategy Design Pattern]]></title><description><![CDATA[Introduction
The Strategy Design Pattern is a behavioral design pattern that allows you to dynamically change the behavior of an object by encapsulating it into different strategies. This pattern enables an object to choose from multiple algorithms a...]]></description><link>https://blog.ashutoshkrris.in/a-beginners-guide-to-strategy-design-pattern</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/a-beginners-guide-to-strategy-design-pattern</guid><category><![CDATA[StrategyPattern]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Java]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Mon, 01 May 2023 08:36:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682925539581/9c9e0de7-d74e-41a4-93ce-35d1bce2ca8b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>The Strategy Design Pattern is a <a target="_blank" href="https://shrinke.me/XNNXyxVS">behavioral design pattern</a> that allows you to dynamically change the behavior of an object by encapsulating it into different strategies. This pattern enables an object to choose from multiple algorithms and behaviors at runtime, rather than statically choosing a single one.</p>
<p>It is based on the principle of composition over inheritance. It defines a family of algorithms, encapsulates each one, and makes them interchangeable at runtime. The core idea behind this pattern is to separate the algorithms from the main object, allowing the object to delegate the algorithm's behavior to one of its contained strategies.</p>
<p>In simpler terms, the Strategy Design Pattern provides a way to extract the behavior of an object into separate classes that can be swapped in and out at runtime. This enables the object to be more flexible and reusable, as different strategies can be easily added or modified without changing the object's core code.</p>
<h3 id="heading-benefits-of-using-the-strategy-design-pattern">Benefits of using the Strategy Design Pattern</h3>
<p>Using the Strategy Design Pattern can provide several benefits, including:</p>
<ol>
<li><p><strong>Improved code flexibility</strong>: By encapsulating the behavior of an object into different strategies, the code becomes more flexible and easier to modify.</p>
</li>
<li><p><strong>Better code reusability</strong>: Since the strategies are encapsulated and interchangeable, they can be reused across different objects and projects.</p>
</li>
<li><p><strong>Encourages better coding practices</strong>: This pattern promotes good coding practices, such as separating concerns and reducing code complexity.</p>
</li>
<li><p><strong>Simplifies testing</strong>: By separating the algorithms and behaviors from the object, testing becomes more straightforward.</p>
</li>
</ol>
<h3 id="heading-use-cases-for-the-strategy-design-pattern">Use cases for the Strategy Design Pattern</h3>
<p>The Strategy Design Pattern can be useful in various scenarios, such as:</p>
<ol>
<li><p><strong>Sorting algorithms</strong>: Different sorting algorithms can be encapsulated into separate strategies and passed to an object that needs sorting.</p>
</li>
<li><p><strong>Validation rules</strong>: Different validation rules can be encapsulated into separate strategies and passed to an object that needs validation.</p>
</li>
<li><p><strong>Text formatting</strong>: Different formatting strategies can be encapsulated into separate strategies and passed to an object that needs formatting.</p>
</li>
<li><p><strong>Database access</strong>: Different database access strategies can be encapsulated into separate strategies and passed to an object that needs to access data from different sources.</p>
</li>
<li><p><strong>Payment strategy</strong>: Different payment methods can be encapsulated into separate strategies and passed to an object that needs to process payments.</p>
</li>
</ol>
<h2 id="heading-understanding-the-strategy-design-pattern">Understanding the Strategy Design Pattern</h2>
<p>The Strategy Design Pattern is a powerful pattern in the world of object-oriented programming. It provides a flexible way to encapsulate and swap the behavior of an object at runtime, enabling code to be more adaptable and easier to maintain. In this section, we will dive deeper into the Strategy Design Pattern, discussing its definition, components, and how it works.</p>
<h3 id="heading-components-of-the-strategy-design-pattern">Components of the Strategy Design Pattern</h3>
<p>The Strategy Design Pattern consists of three primary components:</p>
<ol>
<li><p><strong>Context</strong>: The object that will delegate its behavior to one of the contained strategies. The context maintains a reference to a strategy object and interacts with it through a common interface.</p>
</li>
<li><p><strong>Strategy Interface</strong>: The interface that defines the behavior for all strategies. The strategies implement this interface to provide their unique implementation of the behavior.</p>
</li>
<li><p><strong>Concrete Strategies</strong>: The classes that implement the Strategy Interface. Each strategy encapsulates a specific behavior that the context can switch to at runtime.</p>
</li>
</ol>
<h3 id="heading-how-the-strategy-design-pattern-works">How the Strategy Design Pattern Works</h3>
<p>The Strategy Design Pattern works by separating the behavior of an object from the object itself. The behavior is encapsulated into different strategies, each with its own implementation of the behavior. The context maintains a reference to a strategy object and interacts with it through a common interface. At runtime, the context can swap the current strategy with another one, effectively changing the object's behavior.</p>
<h3 id="heading-examples-of-the-strategy-design-pattern-in-action">Examples of the Strategy Design Pattern in action</h3>
<p>One example of the Strategy Design Pattern in action is in a music streaming service where different subscription tiers have different pricing models. Each subscription tier could have a different pricing strategy that encapsulates its unique pricing logic. The service's billing system would delegate the pricing calculation to the current subscription's strategy, allowing for easy modification and extension of the pricing logic.</p>
<p>Another example is the payment strategy. Different payment methods can be encapsulated into separate strategies, each with its own unique processing logic. A shopping cart application may use the Strategy Design Pattern to encapsulate credit card, PayPal, and cryptocurrency payment methods into separate strategies that can be swapped at runtime. The application's payment processing system would delegate the payment processing logic to the current payment method's strategy, allowing for easy modification and extension of the payment processing logic.</p>
<h2 id="heading-implementing-the-strategy-design-pattern">Implementing the Strategy Design Pattern</h2>
<p>In this section, we will discuss how to implement the Strategy Design Pattern. We will start with a code example that violates the Strategy Design Pattern and explain the problems with it. Then, we will refactor the code to demonstrate how to implement the Strategy Design Pattern.</p>
<p>To implement the Strategy Design Pattern in Java, follow these steps:</p>
<ol>
<li><p>Identify the algorithm or behavior that needs to be encapsulated and made interchangeable.</p>
</li>
<li><p>Define an interface that represents the behavior, with a single method signature that takes in any required parameters.</p>
</li>
<li><p>Implement concrete classes that provide specific implementations of the behavior defined in the interface.</p>
</li>
<li><p>Define a context class that holds a reference to the interface and calls its method when needed.</p>
</li>
<li><p>Modify the context class to allow for the dynamic swapping of the concrete implementations at runtime.</p>
</li>
</ol>
<h3 id="heading-code-example">Code Example</h3>
<p>Let's consider the following code example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> withoutstrategy;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentProcessor</span> </span>{
    <span class="hljs-keyword">private</span> PaymentType paymentType;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span> (paymentType == PaymentType.CREDIT_CARD) {
            System.out.println(<span class="hljs-string">"Processing credit card payment of amount "</span> + amount);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (paymentType == PaymentType.DEBIT_CARD) {
            System.out.println(<span class="hljs-string">"Processing debit card payment of amount "</span> + amount);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (paymentType == PaymentType.PAYPAL) {
            System.out.println(<span class="hljs-string">"Processing PayPal payment of amount "</span> + amount);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Invalid payment type"</span>);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPaymentType</span><span class="hljs-params">(PaymentType paymentType)</span> </span>{
        <span class="hljs-keyword">this</span>.paymentType = paymentType;
    }
}

<span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">PaymentType</span> </span>{
    CREDIT_CARD,
    DEBIT_CARD,
    PAYPAL
}
</code></pre>
<p>In this code, the <code>PaymentProcessor</code> class has a <code>processPayment</code> method that takes a payment amount and processes the payment. The payment type is set using the <code>setPaymentType</code> method, which sets the <code>paymentType</code> field. The <code>processPayment</code> method then checks the value of <code>paymentType</code> and processes the payment accordingly.</p>
<p>The problem with this code is that it violates the <a target="_blank" href="https://shrinke.me/b2Kl">Open-Closed Principle</a>, which states that classes should be open for extension but closed for modification. In this code, if you want to add a new payment type, you would have to modify the <code>processPayment</code> method, which violates the Open-Closed Principle.</p>
<p>The <code>PaymentProcessor</code> class violates the Strategy pattern by using conditional statements to determine the type of payment and then processing it accordingly. This approach can quickly become unmanageable and inflexible as the number of payment types increases.</p>
<p>To fix this problem, you can use the Strategy Design Pattern. First, you define a common interface for all payment strategies, which in this case is the <code>PaymentStrategy</code> interface:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> withstrategy;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span></span>;
}
</code></pre>
<p>You then define concrete implementations of the <code>PaymentStrategy</code> interface for each payment type. For example, here are the <code>CreditCardPaymentStrategy</code>, <code>DebitCardPaymentStrategy</code>, and <code>PaypalPaymentStrategy</code> classes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> withstrategy;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreditCardPaymentStrategy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Processing credit card payment of amount "</span> + amount);
    }
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> withstrategy;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DebitCardPaymentStrategy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Processing debit card payment of amount "</span> + amount);
    }
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> withstrategy;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaypalPaymentStrategy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Processing PayPal payment of amount "</span> + amount);
    }
}
</code></pre>
<p>Finally, you update the <code>PaymentProcessor</code> class to take a <code>PaymentStrategy</code> object in its constructor, which it uses to process the payment:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> withstrategy;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentProcessor</span> </span>{
    <span class="hljs-keyword">private</span> PaymentStrategy paymentStrategy;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PaymentProcessor</span><span class="hljs-params">(PaymentStrategy paymentStrategy)</span> </span>{
        <span class="hljs-keyword">this</span>.paymentStrategy = paymentStrategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        paymentStrategy.processPayment(amount);
    }
}
</code></pre>
<p>This implementation follows the Open-Closed Principle as well as Strategy Pattern because you can add new payment types by creating new implementations of the <code>PaymentStrategy</code> interface without modifying the existing code.</p>
<h3 id="heading-best-practices-for-implementing-the-strategy-design-pattern">Best practices for implementing the Strategy Design Pattern</h3>
<p>Here are a few best practices to keep in mind when implementing the Strategy Design Pattern:</p>
<ol>
<li><p>Keep the interface simple and focused on a single responsibility.</p>
</li>
<li><p>Encapsulate any stateful behavior in the concrete strategy classes, rather than in the context class.</p>
</li>
<li><p>Use dependency injection to pass the concrete strategy to the context class, rather than creating it directly in the context class.</p>
</li>
<li><p>Use an enum or a factory class to provide a centralized place for creating and managing concrete strategy objects.</p>
</li>
</ol>
<h2 id="heading-real-world-applications-of-the-strategy-design-pattern">Real-world Applications of the Strategy Design Pattern</h2>
<p>The Strategy Design Pattern has been used extensively in various real-world applications. One such example is the <strong>Java Collections Framework</strong>. The Collections Framework provides a set of interfaces and classes to represent collections of objects, such as lists, sets, and maps. The framework allows different strategies to be applied to collections based on their behavior.</p>
<p>For instance, the Collections Framework includes a <code>sort()</code> method that allows the sorting of collections. The <code>sort()</code> method takes a Comparator object as an argument, which is responsible for comparing objects within the collection. The Comparator interface defines a strategy for comparing two objects, and the <code>sort()</code> method uses this strategy to sort the collection.</p>
<p>In addition, the Collections Framework also includes the Iterator interface, which defines a strategy for accessing elements of a collection. The Iterator allows the user to traverse the collection without exposing its internal structure, which can change over time. By using the Iterator interface, the user can switch between different strategies for accessing elements of the collection.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this tutorial, we have explored the Strategy Design Pattern and its implementation in Java. We have seen how the Strategy pattern can be used to separate the behavior of an object from its implementation, providing greater flexibility and maintainability in code.</p>
<p>We discussed the components of the Strategy Design Pattern, including the Context, Strategy Interface, and Concrete Strategies. We also provided an example of how the pattern can be used to implement a payment system, allowing for multiple payment options to be implemented using a single interface.</p>
<p>By separating the behavior of an object from its implementation, the Strategy pattern provides greater flexibility and adaptability to changing requirements.</p>
<h3 id="heading-additional-resources">Additional Resources</h3>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=u8DttUrXtEw&amp;list=PL6W8uoQQ2c61X_9e6Net0WdYZidm7zooW&amp;index=3">Strategy Design Pattern Video</a> (Hindi)</p>
</li>
<li><p><a target="_blank" href="https://shrinke.me/solid-principles">SOLID Principles for Better Software Design</a></p>
</li>
<li><p><a target="_blank" href="https://shrinke.me/1ODLeXzl">Design Patterns: A Comprehensive Tutorial</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Patterns: A Comprehensive Tutorial]]></title><description><![CDATA[Introduction
Design patterns are proven solutions to commonly occurring software design problems. In other words, they are reusable templates that help to solve recurring design problems in software development. Design patterns were first introduced ...]]></description><link>https://blog.ashutoshkrris.in/design-patterns-a-comprehensive-tutorial</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/design-patterns-a-comprehensive-tutorial</guid><category><![CDATA[design patterns]]></category><category><![CDATA[Java]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Mon, 01 May 2023 07:17:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682925358213/8ed6787a-61a1-44c8-a4ca-96d2d1b67d82.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Design patterns are proven solutions to commonly occurring software design problems. In other words, they are reusable templates that help to solve recurring design problems in software development. Design patterns were first introduced in the book <a target="_blank" href="http://www.javier8a.com/itc/bd1/articulo.pdf">Design Patterns: Elements of Reusable Object-Oriented Software</a> by the <em>Gang of Four</em> (Gamma, Helm, Johnson, and Vlissides) in 1994.</p>
<p>Design patterns are essential in software development because they provide a common language and framework for communicating design ideas and solutions. They help developers to design robust, flexible, and maintainable software systems. Using design patterns ensures that the software is more reusable, testable, and scalable. Design patterns also promote code reuse and reduce the likelihood of errors and bugs in the software.</p>
<p>In this tutorial, we will explore different types of design patterns, their importance, and the benefits of using them in software development. We will also discuss how to choose the right design pattern for a particular situation and provide examples of design patterns used in real-world applications.</p>
<h2 id="heading-types-of-design-patterns">Types of Design Patterns</h2>
<p>Design patterns are categorized into three main categories: <strong>Creational</strong>, <strong>Structural</strong>, and <strong>Behavioral</strong> patterns.</p>
<h3 id="heading-creational-design-patterns">Creational Design Patterns</h3>
<p>Creational patterns are concerned with object creation mechanisms, trying to create objects in a manner suitable to the situation. There are five types of creational patterns:</p>
<ul>
<li><p><strong>Abstract Factory Pattern</strong>: Provides an interface for creating families of related or dependent objects without specifying their concrete classes.</p>
</li>
<li><p><strong>Builder Pattern</strong>: Separates the construction of a complex object from its representation, allowing the same construction process to create various representations.</p>
</li>
<li><p><strong>Factory Method Pattern</strong>: Defines an interface for creating an object, but lets subclasses decide which class to instantiate.</p>
</li>
<li><p><strong>Object Pool Pattern</strong>: Reuses and shares objects that are expensive to create.</p>
</li>
<li><p><strong>Prototype Pattern</strong>: Creates new objects by copying an existing object, which serves as a prototype.</p>
</li>
</ul>
<ul>
<li><strong>Singleton Pattern</strong>: Ensures that a class has only one instance, and provides a global point of access to it.</li>
</ul>
<h3 id="heading-structural-design-patterns">Structural Design Patterns</h3>
<p>Structural patterns deal with object composition to form larger structures and provide ways to realize relationships between objects. There are seven types of structural patterns:</p>
<ul>
<li><p><strong>Adapter Pattern</strong>: Allows objects with incompatible interfaces to work together by creating an intermediary object that translates one interface to another.</p>
</li>
<li><p><strong>Bridge Pattern</strong>: Decouples an abstraction from its implementation so that the two can vary independently.</p>
</li>
<li><p><strong>Composite Pattern</strong>: Composes objects into tree structures to represent whole-part hierarchies.</p>
</li>
<li><p><strong>Decorator Pattern</strong>: Dynamically adds responsibilities to an object by wrapping it in an object of a decorator class.</p>
</li>
<li><p><strong>Facade Pattern</strong>: Provides a unified interface to a set of interfaces in a subsystem, simplifying the interaction between the client and the subsystem.</p>
</li>
<li><p><strong>Flyweight Pattern</strong>: Uses sharing to support large numbers of fine-grained objects efficiently.</p>
</li>
<li><p><strong>Private Class Data Pattern</strong>: Restricts access to an object's data by encapsulating it within a separate object.</p>
</li>
<li><p><strong>Proxy Pattern</strong>: Provides a surrogate or placeholder for another object to control access to it.</p>
</li>
</ul>
<h3 id="heading-behavioral-design-patterns">Behavioral Design Patterns</h3>
<p>Behavioral patterns deal with communication between objects, focusing on how objects collaborate and fulfill responsibilities. There are eleven types of behavioral patterns:</p>
<ul>
<li><p><strong>Chain of Responsibility Pattern</strong>: Avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.</p>
</li>
<li><p><strong>Command Pattern</strong>: Encapsulates a request as an object, allowing you to parameterize clients with different requests, queue or log requests, and support undoable operations.</p>
</li>
<li><p><strong>Interpreter Pattern</strong>: Defines a grammatical representation of a language and provides an interpreter to parse sentences in the language.</p>
</li>
<li><p><strong>Iterator Pattern</strong>: Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.</p>
</li>
<li><p><strong>Mediator Pattern</strong>: Defines an object that encapsulates how a set of objects interact, promoting loose coupling by keeping objects from referring to each other explicitly.</p>
</li>
<li><p><strong>Memento Pattern</strong>: Captures and externalizes an object's internal state so that it can be restored later, without violating encapsulation.</p>
</li>
<li><p><strong>Null Object Pattern</strong>: Provides a default value for an object, which can be used to avoid null checks in client code</p>
</li>
<li><p><strong>Observer Pattern</strong>: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.</p>
</li>
<li><p><strong>State Pattern</strong>: Allows an object to alter its behavior when its internal state changes so that it appears to change its class.</p>
</li>
<li><p><strong>Strategy Pattern</strong>: Defines a family of algorithms, encapsulates each one and makes them interchangeable.</p>
</li>
<li><p><strong>Template Method Pattern</strong>: Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.</p>
</li>
<li><p><strong>Visitor Pattern</strong>: Separates an algorithm from an object structure by moving the hierarchy of methods into one object.</p>
</li>
</ul>
<h2 id="heading-choosing-the-right-design-pattern">Choosing the Right Design Pattern</h2>
<p>Choosing the right design pattern for a particular situation requires a good understanding of the problem at hand and the available design patterns. It's important to choose a pattern that fits the problem, rather than trying to fit the problem into a preconceived pattern. When choosing a design pattern, there are several factors to consider, including:</p>
<ol>
<li><p><strong>Complexity</strong>: Consider the complexity of the problem and the proposed solution. Some patterns are simple and can be implemented quickly, while others are more complex and may require more time and resources.</p>
</li>
<li><p><strong>Flexibility</strong>: Consider the flexibility of the pattern and how well it will adapt to changes in the problem or requirements. Some patterns are more flexible than others and may be better suited to situations where requirements are likely to change.</p>
</li>
<li><p><strong>Reusability</strong>: Consider the reusability of the pattern and how it can be applied to other problems. Some patterns are more reusable than others and may be better suited to situations where similar problems are likely to occur.</p>
</li>
<li><p><strong>Familiarity</strong>: Consider the familiarity of the pattern and whether it is well-known and widely used. Choosing a well-known pattern can make it easier for other developers to understand and maintain the code.</p>
</li>
</ol>
<p>Examples of when to use certain design patterns include:</p>
<ol>
<li><p>Use the Singleton pattern when you need to ensure that only one instance of a class exists and it needs to be globally accessible.</p>
</li>
<li><p>Use the Factory Method pattern when you need to create objects without specifying the exact class of object that will be created.</p>
</li>
<li><p>Use the Observer pattern when you need to notify a set of objects about changes to another object.</p>
</li>
<li><p>Use the Strategy pattern when you need to dynamically change the behavior of an object at runtime.</p>
</li>
<li><p>Use the Adapter pattern when you need to adapt the interface of an existing class to meet the needs of a new interface.</p>
</li>
</ol>
<p>In summary, choosing the right design pattern requires careful consideration of the problem and the available patterns, taking into account factors such as complexity, flexibility, reusability, and familiarity. Choosing the right pattern can help simplify the code and make it easier to maintain over time.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this tutorial, we have covered the basics of design patterns, including the different types of patterns, how to choose the right pattern for a particular situation, and examples of when to use certain patterns.</p>
<p>Key points to remember include the importance of understanding the problem at hand before choosing a design pattern, the need to consider factors such as complexity, flexibility, reusability, and familiarity when choosing a pattern, and the importance of using patterns to simplify code and make it easier to maintain.</p>
<p>Overall, design patterns are an essential tool in any developer's toolkit. By using patterns effectively, developers can build more robust, maintainable, and scalable software systems that meet the needs of users and businesses alike. We recommend that developers continue to learn and explore design patterns to improve their skills and knowledge of software development.</p>
]]></content:encoded></item><item><title><![CDATA[How To Download YouTube Playlist Using Python]]></title><description><![CDATA[YouTube is the world's largest video-sharing platform with millions of videos uploaded daily. You often come across a playlist of videos on YouTube that you want to watch offline or save for future reference. However, downloading a single video from ...]]></description><link>https://blog.ashutoshkrris.in/how-to-download-youtube-playlist-using-python</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-download-youtube-playlist-using-python</guid><category><![CDATA[Python]]></category><category><![CDATA[pytube]]></category><category><![CDATA[playlist-downloader]]></category><category><![CDATA[automation]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[video downloader]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sun, 30 Apr 2023 17:54:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682877181699/4afcd052-449c-4420-af73-1de00b3bdb88.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>YouTube is the world's largest video-sharing platform with millions of videos uploaded daily. You often come across a playlist of videos on YouTube that you want to watch offline or save for future reference. However, downloading a single video from YouTube is easy, but when it comes to downloading an entire playlist, can be a daunting task. In such cases, automating the process using Python can save time and effort.</p>
<p>In this tutorial, you will be using the Pytube library in Python to download entire YouTube playlists in various resolutions, including the high-quality 2160p resolution. Pytube is a lightweight library that allows easy access to YouTube videos and metadata. With Pytube, we can easily extract video URLs, download videos, and even extract audio from videos. So, let's dive into the tutorial and learn how to download a YouTube playlist using Python.</p>
<blockquote>
<p>If you're in a hurry, jump to the <a target="_blank" href="https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50">GitHub gist</a> to get the code immediately.</p>
</blockquote>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow this tutorial, you should have a basic understanding of Python programming language, including installing Python packages using pip.</p>
<p>You will also need to install the Pytube library, which can be installed using pip. Open a command prompt or terminal window and type the following command:</p>
<pre><code class="lang-bash">pip install pytube tqdm tenacity
</code></pre>
<p>Apart from Python and Pytube, you will also need to have FFmpeg installed on your system. FFmpeg is a command-line tool used for handling multimedia files. It is required for Pytube to be able to download videos in various resolutions. You can download FFmpeg from the <a target="_blank" href="https://www.ffmpeg.org/download.html">official website</a> and follow the installation instructions for your operating system.</p>
<p>We've also installed <code>tqdm</code> for progress bar, and <code>tenacity</code> to implement retry mechanism.</p>
<blockquote>
<p>Note: PyTube sometimes doesn't work. In that case, you can install the <a target="_blank" href="https://github.com/JuanBindez/pytubefix">pytubefix</a> library.</p>
</blockquote>
<h2 id="heading-lets-code-it">Let's Code It!</h2>
<p>Roll up your sleeves, fire up your favorite code editor, and let's get started!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682874768386/bd85e9cc-f6b0-40ba-814b-5d8f72deacb5.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-import-the-libraries">Import the Libraries</h3>
<p>Let's import the necessary libraries for the program to run correctly.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">from</span> pytube <span class="hljs-keyword">import</span> Playlist, YouTube
<span class="hljs-comment"># Comment above line and uncomment below line if you're using pytubefix</span>
<span class="hljs-keyword">from</span> pytubefix <span class="hljs-keyword">import</span> Playlist, YouTube
</code></pre>
<p>The code imports the <code>os</code> module to handle operating system functionalities, <code>re</code> module to handle regular expressions, and <code>pytube</code> module to download the YouTube playlist.</p>
<h3 id="heading-util-function-to-sanitize-filenames">Util Function to Sanitize Filenames</h3>
<p>Often we find that the playlist or the video title contains special characters, which few operating systems don't support. For example, Windows will not support a video with the title "Who are you?" because it contains a question mark(?). We'll write a function to sanitize such names:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sanitize_filename</span>(<span class="hljs-params">filename</span>):</span>
    <span class="hljs-keyword">return</span> re.sub(<span class="hljs-string">r'[&lt;&gt;:"/\\|?*]'</span>, <span class="hljs-string">'-'</span>, filename)
</code></pre>
<p>The <code>sanitize_filename</code> function replaces invalid characters in filenames with a hyphen (<code>-</code>).</p>
<h3 id="heading-create-the-function">Create the Function</h3>
<p>Let's define a function called <code>download_playlist</code>. The function takes two parameters; the playlist URL and the desired video resolution.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">download_playlist</span>(<span class="hljs-params">playlist_url, resolution</span>):</span>
    playlist = Playlist(playlist_url)
    playlist_name = sanitize_filename(re.sub(<span class="hljs-string">r'\W+'</span>, <span class="hljs-string">'-'</span>, playlist.title))

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(playlist_name):
        os.mkdir(playlist_name)
</code></pre>
<p>It first creates a new <code>Playlist</code> object using the Pytube library and extracts the name of the playlist. It then checks if a folder with the same name exists in the current working directory. If not, it creates a new folder with the playlist name.</p>
<p>Note that the <code>re.sub()</code> function replaces any non-alphanumeric characters in the playlist title with a hyphen ("-") character. We do so because folder and file names in most file systems have restrictions on the characters they can contain.</p>
<h3 id="heading-downloading-the-videos">Downloading the Videos</h3>
<p>The <code>Playlist</code> object provides a <code>videos</code> property which is iterable of <code>YouTube</code> objects. You first iterate through the list of videos in the playlist using a <code>for</code> loop and <code>enumerate</code> function.:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
    ...
</code></pre>
<p>The <code>start</code> parameter set to 1 to start counting from 1 instead of 0 because you're going to use the index in the filenames. Thus it makes sense to start from 1.</p>
<p>The <code>enumerate</code> function is used in conjunction with <code>tqdm</code> to keep track of the current index in the iteration, making it easier to monitor the progress and status of the download process for each video in the playlist. The <code>tqdm</code> function is wrapped around <code>playlist.videos</code> to create a progress bar that visualizes the progress of the loop. The <code>desc</code> parameter is used to set a description for the progress bar, here specified as "Downloading playlist", which helps in indicating the ongoing process to the user. Additionally, the <code>unit</code> parameter is set to "video", which labels each step in the progress bar, thereby clarifying that each increment corresponds to the processing of one video.</p>
<p>Next, create a <code>YouTube</code> object for each video using its watch URL:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
        yt = YouTube(video.watch_url, on_progress_callback=progress_function)
</code></pre>
<p>The second argument, <code>on_progress_callback=progress_function</code>, sets up a callback function that will be called periodically to provide updates on the download progress. We will define it later.</p>
<p>Filter the available video streams to select the one with the desired resolution, and get its filename:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
    yt = YouTube(video.watch_url, on_progress_callback=progress_function)
    video_streams = yt.streams.filter(res=resolution)

    video_filename = sanitize_filename(<span class="hljs-string">f"<span class="hljs-subst">{index}</span>. <span class="hljs-subst">{yt.title}</span>.mp4"</span>)
    video_path = os.path.join(playlist_name, video_filename)
</code></pre>
<p>The above code snippet filters available video streams to match a specified resolution and prepares the filename and path for downloading a YouTube video.</p>
<p>Check if the video already exists. If it does, skip downloading this video and move on to the next one:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
    yt = YouTube(video.watch_url, on_progress_callback=progress_function)
    video_streams = yt.streams.filter(res=resolution)

    video_filename = sanitize_filename(<span class="hljs-string">f"<span class="hljs-subst">{index}</span>. <span class="hljs-subst">{yt.title}</span>.mp4"</span>)
    video_path = os.path.join(playlist_name, video_filename)

    <span class="hljs-keyword">if</span> os.path.exists(video_path):
        print(<span class="hljs-string">f"<span class="hljs-subst">{video_filename}</span> already exists"</span>)
        <span class="hljs-keyword">continue</span>
</code></pre>
<p>If the desired resolution is not available, download the video with the highest resolution instead:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
    ...

    <span class="hljs-keyword">if</span> os.path.exists(video_path):
        print(<span class="hljs-string">f"<span class="hljs-subst">{video_filename}</span> already exists"</span>)
        <span class="hljs-keyword">continue</span>

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> video_streams:
        highest_resolution_stream = yt.streams.get_highest_resolution()
        video_name = sanitize_filename(highest_resolution_stream.default_filename)
        print(<span class="hljs-string">f"Downloading <span class="hljs-subst">{video_name}</span> in <span class="hljs-subst">{highest_resolution_stream.resolution}</span>"</span>)
        download_with_retries(highest_resolution_stream, video_path)
    <span class="hljs-keyword">else</span>:
        video_stream = video_streams.first()
        video_name = sanitize_filename(video_stream.default_filename)
        print(<span class="hljs-string">f"Downloading video for <span class="hljs-subst">{video_name}</span> in <span class="hljs-subst">{resolution}</span>"</span>)
        download_with_retries(video_stream, <span class="hljs-string">"video.mp4"</span>)
</code></pre>
<p>If no video streams with the desired resolution are found, the code selects the highest-resolution stream available. It then creates a sanitized filename for this stream and proceeds to download it using the <code>download_with_retries</code> function.</p>
<p>If streams with the desired resolution are available, the code selects the first stream in the filtered list. It creates a sanitized filename for this stream and downloads it as <code>"video.mp4"</code>. This approach ensures that the best available quality is used or the specified resolution is downloaded if available.</p>
<p>If the desired resolution is available, you don't have to download it directly. If you do so, the downloaded video won't have sound. Instead, download both the video and audio streams separately, and merge them using the FFmpeg library to create the final video file. Finally, rename the merged file and delete the temporary video and audio files:</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
    ...

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> video_streams:
        ...
    <span class="hljs-keyword">else</span>:
        video_stream = video_streams.first()
        video_name = sanitize_filename(video_stream.default_filename)
        print(<span class="hljs-string">f"Downloading video for <span class="hljs-subst">{video_name}</span> in <span class="hljs-subst">{resolution}</span>"</span>)
        download_with_retries(video_stream, <span class="hljs-string">"video.mp4"</span>)

        audio_stream = yt.streams.get_audio_only()
        download_with_retries(audio_stream, <span class="hljs-string">"audio.mp4"</span>)

        os.system(<span class="hljs-string">"ffmpeg -y -i video.mp4 -i audio.mp4 -c:v copy -c:a aac final.mp4 -loglevel quiet -stats"</span>)
        os.rename(<span class="hljs-string">"final.mp4"</span>, video_path)
        os.remove(<span class="hljs-string">"video.mp4"</span>)
        os.remove(<span class="hljs-string">"audio.mp4"</span>)

        print(<span class="hljs-string">"----------------------------------"</span>)
</code></pre>
<p>The video stream is initially downloaded as <code>video.mp4</code> and the audio stream is downloaded as <code>audio.mp4</code>. Next, the <code>ffmpeg</code> command takes two input files (<code>video.mp4</code> and <code>audio.mp4</code>), copies the video codec from the input file and uses the AAC codec for audio, and saves the output as <code>final.mp4</code>. The output file is created by merging the video and audio streams from the two input files.</p>
<p>After <code>ffmpeg</code> finishes processing, the <code>final.mp4</code> is renamed <code>video_path</code> and the video and audio stream files are deleted.</p>
<h3 id="heading-the-downloadplaylist-function">The <code>download_playlist</code> Function</h3>
<p>At this point, you have completed the <code>download_playlist</code> function. It should look like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">download_playlist</span>(<span class="hljs-params">playlist_url, resolution</span>):</span>
    playlist = Playlist(playlist_url)
    playlist_name = sanitize_filename(re.sub(<span class="hljs-string">r'\W+'</span>, <span class="hljs-string">'-'</span>, playlist.title))

    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.exists(playlist_name):
        os.mkdir(playlist_name)

    <span class="hljs-keyword">for</span> index, video <span class="hljs-keyword">in</span> enumerate(tqdm(playlist.videos, desc=<span class="hljs-string">"Downloading playlist"</span>, unit=<span class="hljs-string">"video"</span>), start=<span class="hljs-number">1</span>):
        yt = YouTube(video.watch_url, on_progress_callback=progress_function)
        video_streams = yt.streams.filter(res=resolution)

        video_filename = sanitize_filename(<span class="hljs-string">f"<span class="hljs-subst">{index}</span>. <span class="hljs-subst">{yt.title}</span>.mp4"</span>)
        video_path = os.path.join(playlist_name, video_filename)

        <span class="hljs-keyword">if</span> os.path.exists(video_path):
            print(<span class="hljs-string">f"<span class="hljs-subst">{video_filename}</span> already exists"</span>)
            <span class="hljs-keyword">continue</span>

        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> video_streams:
            highest_resolution_stream = yt.streams.get_highest_resolution()
            video_name = sanitize_filename(highest_resolution_stream.default_filename)
            print(<span class="hljs-string">f"Downloading <span class="hljs-subst">{video_name}</span> in <span class="hljs-subst">{highest_resolution_stream.resolution}</span>"</span>)
            download_with_retries(highest_resolution_stream, video_path)
        <span class="hljs-keyword">else</span>:
            video_stream = video_streams.first()
            video_name = sanitize_filename(video_stream.default_filename)
            print(<span class="hljs-string">f"Downloading video for <span class="hljs-subst">{video_name}</span> in <span class="hljs-subst">{resolution}</span>"</span>)
            download_with_retries(video_stream, <span class="hljs-string">"video.mp4"</span>)

            audio_stream = yt.streams.get_audio_only()
            print(<span class="hljs-string">f"Downloading audio for <span class="hljs-subst">{video_name}</span>"</span>)
            download_with_retries(audio_stream, <span class="hljs-string">"audio.mp4"</span>)

            os.system(<span class="hljs-string">"ffmpeg -y -i video.mp4 -i audio.mp4 -c:v copy -c:a aac final.mp4 -loglevel quiet -stats"</span>)
            os.rename(<span class="hljs-string">"final.mp4"</span>, video_path)
            os.remove(<span class="hljs-string">"video.mp4"</span>)
            os.remove(<span class="hljs-string">"audio.mp4"</span>)

        print(<span class="hljs-string">"----------------------------------"</span>)
</code></pre>
<p>A line of dashes is also printed after every iteration to separate each video as they are downloaded.</p>
<h3 id="heading-function-to-download-with-retries">Function to Download with Retries</h3>
<p>In the above code snippet, we have called a <code>download_with_retries</code> method. Let us define that:</p>
<pre><code class="lang-python"><span class="hljs-meta">@retry(stop=stop_after_attempt(5), wait=wait_fixed(2))</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">download_with_retries</span>(<span class="hljs-params">stream, filename</span>):</span>
    stream.download(filename=filename)
</code></pre>
<p>The function attempts to download a file using the provided stream, with retry logic to handle potential failures. It is decorated with the <code>@retry</code> decorator from the <code>tenacity</code> library, which adds retry functionality. The decorator parameters specify the retry behavior:</p>
<ul>
<li><p><code>stop=stop_after_attempt(5)</code>: This tells the function to stop retrying after 5 attempts.</p>
</li>
<li><p><code>wait=wait_fixed(2)</code>: This specifies a fixed wait time of 2 seconds between each retry attempt.</p>
</li>
</ul>
<p>Inside the function, <code>stream.download(filename=filename)</code> is called to perform the actual download. If the download fails, the retry mechanism will automatically retry up to 5 times, with a 2-second pause between attempts. This ensures a more robust download process by handling transient errors and improving reliability.</p>
<h3 id="heading-function-to-handle-progress-bar">Function to Handle Progress Bar</h3>
<p>We've also used a callback function to show the progress bar. Let us define that:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">progress_function</span>(<span class="hljs-params">stream, chunk, bytes_remaining</span>):</span>
    total_size = stream.filesize
    bytes_downloaded = total_size - bytes_remaining
    percentage_of_completion = bytes_downloaded / total_size * <span class="hljs-number">100</span>
    print(<span class="hljs-string">f"Downloading... <span class="hljs-subst">{percentage_of_completion:<span class="hljs-number">.2</span>f}</span>% complete"</span>, end=<span class="hljs-string">"\r"</span>)
</code></pre>
<p>The function takes three parameters:</p>
<ul>
<li><p><code>stream</code>: Represents the video stream being downloaded.</p>
</li>
<li><p><code>chunk</code>: The current chunk of data being downloaded.</p>
</li>
<li><p><code>bytes_remaining</code>: The number of bytes remaining to download.</p>
</li>
</ul>
<p>Inside the function:</p>
<ol>
<li><p><code>total_size = stream.filesize</code>: Retrieves the total size of the file from the stream.</p>
</li>
<li><p><code>bytes_downloaded = total_size - bytes_remaining</code>: Calculates the number of bytes already downloaded by subtracting the remaining bytes from the total size.</p>
</li>
<li><p><code>percentage_of_completion = bytes_downloaded / total_size * 100</code>: Computes the percentage of completion by dividing the bytes downloaded by the total size and multiplying by 100.</p>
</li>
</ol>
<p>The function then prints the progress as a percentage, updating the same line in the console with <code>end="\r"</code>, which ensures the progress is displayed on the same line, providing a real-time update on the download status.</p>
<h3 id="heading-main-function">Main Function</h3>
<p>Let's create the main function that takes input from the user for the playlist URL and desired video resolution. It then calls the <code>download_playlist</code> function with the user's inputs.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    playlist_url = input(<span class="hljs-string">"Enter the playlist url: "</span>)
    resolutions = [<span class="hljs-string">"240p"</span>, <span class="hljs-string">"360p"</span>, <span class="hljs-string">"480p"</span>, <span class="hljs-string">"720p"</span>, <span class="hljs-string">"1080p"</span>, <span class="hljs-string">"1440p"</span>, <span class="hljs-string">"2160p"</span>]
    resolution = input(<span class="hljs-string">f"Please select a resolution <span class="hljs-subst">{resolutions}</span>: "</span>)
    download_playlist(playlist_url, resolution)
</code></pre>
<h2 id="heading-completed-code">Completed Code</h2>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="830c954511db460804b43a8a49374e50"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50" class="embed-card">https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50</a></div><p> </p>
<h2 id="heading-demo">Demo</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/c8nyDRX3wn8">https://youtu.be/c8nyDRX3wn8</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how you can use PyTube and FFmpeg libraries to download videos from a YouTube playlist in high resolutions such as 1080p, 1440p, and even 2160p.</p>
<p>I hope you found the tutorial helpful. If so, don't forget to star the <a target="_blank" href="https://gist.github.com/ashutoshkrris/830c954511db460804b43a8a49374e50">GitHub gist</a> and share this tutorial with others.</p>
<blockquote>
<p>The code has been tested with Pytubefix 6.5.1. It may not work properly at a later point in time.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[SOLID Principles for Better Software Design]]></title><description><![CDATA[Introduction
SOLID principles are a set of guidelines for writing high-quality, maintainable, and scalable software. They were introduced by Robert C. Martin, a renowned software engineer, and consultant, in his 2000 paper “Design Principles and Desi...]]></description><link>https://blog.ashutoshkrris.in/solid-principles-for-better-software-design</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/solid-principles-for-better-software-design</guid><category><![CDATA[Java]]></category><category><![CDATA[SOLID principles]]></category><category><![CDATA[design principles]]></category><category><![CDATA[low level design]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sat, 29 Apr 2023 19:27:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682796174524/b91c28da-8618-49cc-870e-86ba4bc049b7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>SOLID principles are a set of guidelines for writing high-quality, maintainable, and scalable software. They were introduced by Robert C. Martin, a renowned software engineer, and consultant, in his 2000 paper <a target="_blank" href="https://fi.ort.edu.uy/innovaportal/file/2032/1/design_principles.pdf">“Design Principles and Design Patterns”</a> to help developers write software that is easy to understand, modify, and extend. These concepts were later built upon by Michael Feathers, who introduced us to the SOLID acronym.</p>
<p>The SOLID acronym stands for:</p>
<ul>
<li><p><strong>S</strong>ingle Responsibility Principle (SRP)</p>
</li>
<li><p><strong>O</strong>pen-Closed Principle (OCP)</p>
</li>
<li><p><strong>L</strong>iskov Substitution Principle (LSP)</p>
</li>
<li><p><strong>I</strong>nterface Segregation Principle (ISP)</p>
</li>
<li><p><strong>D</strong>ependency Inversion Principle (DIP)</p>
</li>
</ul>
<p>These principles provide a way for developers to organize their code and create software that is flexible, easy to change, and testable. Applying SOLID principles can lead to code that is more modular, maintainable, and extensible, and it can make it easier for developers to work collaboratively on a codebase.</p>
<p>In this tutorial, we will explore each of the SOLID principles in detail, explain why they are important, and provide examples of how they can be applied in practice. By the end of this tutorial, you should have a good understanding of the SOLID principles and how to apply them to your software development projects.</p>
<h2 id="heading-single-responsibility-principle">Single Responsibility Principle</h2>
<p>The Single Responsibility Principle (SRP) states that <strong>a class should have only one reason to change</strong>, or in other words, <strong>it should have only one responsibility</strong>. This means that a class should have only one job to do, and it should do it well.</p>
<p>If a class has too many responsibilities, it can become hard to understand, maintain, and modify. Changes to one responsibility can inadvertently affect another responsibility, leading to unintended consequences and bugs. By following SRP, we can create code that is more modular, easier to understand, and less prone to errors.</p>
<p>Let's take an example that violates the SRP:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Marker</span> </span>{
    String name;
    String color;
    <span class="hljs-keyword">int</span> price;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Marker</span><span class="hljs-params">(String name, String color, <span class="hljs-keyword">int</span> price)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.color = color;
        <span class="hljs-keyword">this</span>.price = price;
    }
}
</code></pre>
<p>The above code defines a simple <code>Marker</code> class having three instance variables - <code>name</code>, <code>color</code> and <code>price</code>.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Invoice</span> </span>{
    <span class="hljs-keyword">private</span> Marker marker;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> quantity;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Invoice</span><span class="hljs-params">(Marker marker, <span class="hljs-keyword">int</span> quantity)</span> </span>{
        <span class="hljs-keyword">this</span>.marker = marker;
        <span class="hljs-keyword">this</span>.quantity = quantity;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">calculateTotal</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> marker.price * <span class="hljs-keyword">this</span>.quantity;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printInvoice</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// printing implementation</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">saveToDb</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// save to database implementation</span>
    }
}
</code></pre>
<p>The above <code>Invoice</code> class violates SRP because it has multiple responsibilities - it is responsible for calculating the total amount, printing the invoice, and saving the invoice to the database. As a result, if the calculation logic changes, such as the addition of taxes, the <code>calculateTotal()</code> method would require modification. Similarly, if the printing or database-saving implementation changes at any point, the class would need to be changed. Therefore, there are several reasons for the class to be modified, which could lead to increased maintenance costs and complexity.</p>
<p>Here's how you can modify the code to follow SRP:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Invoice</span> </span>{
    <span class="hljs-keyword">private</span> Marker marker;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> quantity;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Invoice</span><span class="hljs-params">(Marker marker, <span class="hljs-keyword">int</span> quantity)</span> </span>{
        <span class="hljs-keyword">this</span>.marker = marker;
        <span class="hljs-keyword">this</span>.quantity = quantity;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">calculateTotal</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> marker.price * <span class="hljs-keyword">this</span>.quantity;
    }
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvoiceDao</span> </span>{
    <span class="hljs-keyword">private</span> Invoice invoice;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvoiceDao</span><span class="hljs-params">(Invoice invoice)</span> </span>{
        <span class="hljs-keyword">this</span>.invoice = invoice;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">saveToDb</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// save to database implementation</span>
    }
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvoicePrinter</span> </span>{
    <span class="hljs-keyword">private</span> Invoice invoice;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvoicePrinter</span><span class="hljs-params">(Invoice invoice)</span> </span>{
        <span class="hljs-keyword">this</span>.invoice = invoice;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printInvoice</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// printing implementation</span>
    }
}
</code></pre>
<p>In this refactored example, we have split the responsibilities of the <code>Invoice</code> class into three separate classes - <code>Invoice</code>, <code>InvoiceDao</code>, and <code>InvoicePrinter</code>. The <code>Invoice</code> class is responsible only for calculating the total amount, and the printing and saving responsibilities have been delegated to separate classes. This makes the code more modular, easier to understand, and less prone to errors.</p>
<h2 id="heading-open-closed-principle">Open-Closed Principle</h2>
<p>The Open-Closed Principle (OCP) states that <strong>software entities (classes, modules, functions, etc.) should be open for extension but closed for modification</strong>. This means that the behavior of a software entity can be extended without modifying its source code.</p>
<p>The OCP is essential because it promotes software extensibility and maintainability. By allowing software entities to be extended without modification, developers can add new functionality without the risk of breaking existing code. This results in code that is easier to maintain, extend, and reuse.</p>
<p>Let's take the previous example again.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvoiceDao</span> </span>{
    <span class="hljs-keyword">private</span> Invoice invoice;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvoiceDao</span><span class="hljs-params">(Invoice invoice)</span> </span>{
        <span class="hljs-keyword">this</span>.invoice = invoice;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">saveToDb</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// save to database implementation</span>
    }
}
</code></pre>
<p>The <code>InvoiceDao</code> class has a single responsibility of saving the invoice to the database. But, suppose there's a new requirement to save the invoice to a file as well. One way to implement this requirement would be to modify the existing <code>InvoiceDao</code> class by adding a <code>saveToFile()</code> method. However, this violates the Open-Closed Principle because it modifies the existing code that has already been tested and is live in production.</p>
<p>To follow the OCP, a better solution would be to create an <code>InvoiceDao</code> interface and implement it separately for database and file saving as shown below:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">InvoiceDao</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save</span><span class="hljs-params">(Invoice invoice)</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DatabaseInvoiceDao</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">InvoiceDao</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save</span><span class="hljs-params">(Invoice invoice)</span> </span>{
        <span class="hljs-comment">// save to database implementation</span>
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileInvoiceDao</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">InvoiceDao</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">save</span><span class="hljs-params">(Invoice invoice)</span> </span>{
        <span class="hljs-comment">// save to file implementation</span>
    }
}
</code></pre>
<p>This way, if there's a new requirement to save the invoice to another data store, you can implement a new <code>InvoiceDao</code> implementation without modifying the existing code. Thus, the <code>InvoiceDao</code> interface is open for extension and closed for modification, which follows the OCP.</p>
<h2 id="heading-liskov-substitution-principle"><strong>L</strong>iskov Substitution Principle</h2>
<p>The Liskov Substitution Principle (LSP) states that <strong>any instance of a derived class should be substitutable for an instance of its base class without affecting the correctness of the program</strong>. In other words, a derived class should behave like its base class in all contexts. In more simple terms, if class A is a subtype of class B, you should be able to replace B with A without breaking the behavior of your program.</p>
<p>The importance of LSP lies in its ability to ensure that the behavior of a program remains consistent and predictable when substituting objects of different classes. Violating LSP can lead to unexpected behavior, bugs, and maintainability issues.</p>
<p>Let's take an example.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Bike</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">turnOnEngine</span><span class="hljs-params">()</span></span>;

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">accelerate</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>In the given example, the interface <code>Bike</code> has two methods, <code>turnOnEngine()</code> and <code>accelerate()</code>. Two classes implement this interface, <code>Motorbike</code> and <code>Bicycle</code>.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Motorbike</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Bike</span> </span>{

    <span class="hljs-keyword">boolean</span> isEngineOn;
    <span class="hljs-keyword">int</span> speed;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">turnOnEngine</span><span class="hljs-params">()</span> </span>{
        isEngineOn = <span class="hljs-keyword">true</span>;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">accelerate</span><span class="hljs-params">()</span> </span>{
        speed += <span class="hljs-number">5</span>;
    }
}
</code></pre>
<p><code>Motorbike</code> correctly implements the <code>turnOnEngine()</code> method, as it sets the <code>isEngineOn</code> boolean to true. It also correctly implements the <code>accelerate()</code> method by increasing the <code>speed</code> by 5.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bicycle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Bike</span> </span>{

    <span class="hljs-keyword">boolean</span> isEngineOn;
    <span class="hljs-keyword">int</span> speed;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">turnOnEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> AssertionError(<span class="hljs-string">"There is no engine!"</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">accelerate</span><span class="hljs-params">()</span> </span>{
        speed += <span class="hljs-number">5</span>;
    }
}
</code></pre>
<p>However, the <code>Bicycle</code> class throws an <code>AssertionError</code> in the <code>turnOnEngine()</code> method because it has no engine. This means that an instance of <code>Bicycle</code> cannot be substituted for an instance of <code>Bike</code> without breaking the behavior of the program.</p>
<p>In other words, if the <code>Bicycle</code> class is considered a subtype of the <code>Bike</code> interface, then according to LSP, any instance of <code>Bike</code> should be replaceable with an instance of <code>Bicycle</code> without altering the correctness of the program. But in this case, it's not true because <code>Bicycle</code> throws an <code>AssertionError</code> while trying to turn on the engine. Therefore, the code violates the LSP.</p>
<h2 id="heading-interface-segregation-principle"><strong>I</strong>nterface Segregation Principle</h2>
<p>The Interface Segregation Principle (ISP) focuses on designing interfaces that are specific to their client's needs. It states that no client should be forced to depend on methods it does not use.</p>
<p>The principle suggests that <strong>instead of creating a large interface that covers all the possible methods, it's better to create smaller, more focused interfaces for specific use cases</strong>. This approach results in interfaces that are more cohesive and less coupled.</p>
<p>Consider a <code>Vehicle</code> interface as below:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">startEngine</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">stopEngine</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">drive</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>And then you have a class called <code>Car</code> that implements the <code>Vehicle</code> interface:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Vehicle</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">stopEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drive</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnsupportedOperationException(<span class="hljs-string">"This vehicle cannot fly."</span>);
    }
}
</code></pre>
<p>In this example, the <code>Vehicle</code> interface has too many methods. The <code>Car</code> class is forced to implement all of them, even though they cannot fly. This violates the ISP because the <code>Vehicle</code> interface is not properly segregated into smaller interfaces based on related functionality.</p>
<p>Let's understand how you can follow ISP here. Suppose you refactor the <code>Vehicle</code> interface into smaller, more focused interfaces:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Drivable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">startEngine</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">stopEngine</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">drive</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Flyable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p>Now, you can have a class called <code>Car</code> that only implements the <code>Drivable</code> interface:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Drivable</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">stopEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drive</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }
}
</code></pre>
<p>And, thanks to interface segregation, you can have another class called <code>Airplane</code> that implements both the <code>Drivable</code> and <code>Flyable</code> interfaces:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Airplane</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Drivable</span>, <span class="hljs-title">Flyable</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">stopEngine</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">drive</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// implementation</span>
    }
}
</code></pre>
<p>In this example, you have properly segregated the <code>Vehicle</code> interface into smaller interfaces based on related functionality. This adheres to the ISP and makes your code more flexible and maintainable.</p>
<h2 id="heading-dependency-inversion-principle">Dependency Inversion Principle</h2>
<p>The Dependency Inversion Principle (DIP) states that <strong>high-level modules should not depend on low-level modules, but both should depend on abstractions</strong>. Abstractions should not depend on details; details should depend on abstractions. This principle aims to reduce coupling between modules, increase modularity, and make the code easier to maintain, test, and extend.</p>
<p>For example, consider a scenario where you have a class that needs to use an instance of another class. In the traditional approach, the first class would directly create an instance of the second class, leading to a tight coupling between them. This makes it difficult to change the implementation of the second class or to test the first class independently. However, if you apply the DIP, the first class would depend on an abstraction of the second class instead of the implementation, making it possible to easily change the implementation and test the first class independently.</p>
<p>Here is an example that violates the DIP:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeatherTracker</span> </span>{
    <span class="hljs-keyword">private</span> String currentConditions;
    <span class="hljs-keyword">private</span> Emailer emailer;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherTracker</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>.emailer = <span class="hljs-keyword">new</span> Emailer();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setCurrentConditions</span><span class="hljs-params">(String weatherDescription)</span> </span>{
        <span class="hljs-keyword">this</span>.currentConditions = weatherDescription;
        <span class="hljs-keyword">if</span> (weatherDescription == <span class="hljs-string">"rainy"</span>) {
            emailer.sendEmail(<span class="hljs-string">"It is rainy"</span>);
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Emailer</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendEmail</span><span class="hljs-params">(String message)</span> </span>{
        System.out.println(<span class="hljs-string">"Email sent: "</span> + message);
    }
}
</code></pre>
<p>In this example, the <code>WeatherTracker</code> class directly creates an instance of the <code>Emailer</code> class, making it tightly coupled to the implementation. This makes it difficult to change the implementation of the <code>Emailer</code> class or to test the <code>WeatherTracker</code> class independently.</p>
<p>Here is an example of how to apply the DIP to the above code:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Notifier</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">alertWeatherConditions</span><span class="hljs-params">(String weatherDescription)</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WeatherTracker</span> </span>{
    <span class="hljs-keyword">private</span> String currentConditions;
    <span class="hljs-keyword">private</span> Notifier notifier;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WeatherTracker</span><span class="hljs-params">(Notifier notifier)</span> </span>{
        <span class="hljs-keyword">this</span>.notifier = notifier;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setCurrentConditions</span><span class="hljs-params">(String weatherDescription)</span> </span>{
        <span class="hljs-keyword">this</span>.currentConditions = weatherDescription;
        <span class="hljs-keyword">if</span> (weatherDescription == <span class="hljs-string">"rainy"</span>) {
            notifier.alertWeatherConditions(<span class="hljs-string">"It is rainy"</span>);
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Emailer</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Notifier</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">alertWeatherConditions</span><span class="hljs-params">(String weatherDescription)</span> </span>{
        System.out.println(<span class="hljs-string">"Email sent: "</span> + weatherDescription);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SMS</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Notifier</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">alertWeatherConditions</span><span class="hljs-params">(String weatherDescription)</span> </span>{
        System.out.println(<span class="hljs-string">"SMS sent: "</span> + weatherDescription);
    }
}
</code></pre>
<p>In this example, you created a <code>Notifier</code> interface that defines the <code>alertWeatherConditions</code> method. The <code>WeatherTracker</code> class now depends on this interface instead of the <code>Emailer</code> class, making it possible to easily change the implementation and test the <code>WeatherTracker</code> class independently. You also created two implementations of the <code>Notifier</code> interface, <code>Emailer</code>, and <code>SMS</code>, to demonstrate how you can change the implementation of the <code>WeatherTracker</code> class without affecting its behavior.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned about SOLID principles which is a very important part of Design Principles. By applying these principles in your software development projects, you can create code that is easier to maintain, extend, and modify, leading to more robust, flexible, and reusable software. This will also lead to better collaboration among team members, as the code becomes more modular and easier to work with.</p>
<h4 id="heading-references">References</h4>
<ul>
<li><p><a target="_blank" href="https://www.baeldung.com/solid-principles">A Solid Guide to SOLID Principles</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=XI7zep97c-Y">SOLID Principles with Easy Examples</a> (Hindi Video)</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Build and Publish Python Packages With Poetry]]></title><description><![CDATA[A Python package is a collection of Python modules that can be easily distributed and installed. It allows developers to reuse code across multiple projects and share it with others.
Python packages typically include a set of functions, classes, or o...]]></description><link>https://blog.ashutoshkrris.in/how-to-build-and-publish-python-packages-with-poetry</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/how-to-build-and-publish-python-packages-with-poetry</guid><category><![CDATA[Python]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Thu, 06 Apr 2023 04:24:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1680754993021/c163b780-5f8f-46fc-a0fa-861991275f73.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A Python package is a collection of Python modules that can be easily distributed and installed. It allows developers to reuse code across multiple projects and share it with others.</p>
<p>Python packages typically include a set of functions, classes, or other components that serve a specific purpose, such as data analysis, web development, or machine learning.</p>
<p>You might have used built-in Python packages such as <code>os</code>, <code>sys</code>, or <code>math</code>, or external dependencies such as <code>requests</code>, <code>pandas</code>, or <code>numpy</code> in your Python projects.</p>
<p>The tutorial will guide you through the process of creating and publishing a Python package with <a target="_blank" href="https://python-poetry.org/">Poetry</a>. You will build a phone number validation package to check if a given phone number is valid. Along the way, you will learn how to use Poetry to manage dependencies, define package configurations, and write tests for the package.</p>
<p>By the end of this tutorial, you should have a good understanding of how to use Poetry to create and publish your own Python packages.</p>
<h2 id="heading-what-is-poetry">What is Poetry?</h2>
<p>Poetry is a modern tool for package management in Python that simplifies the process of creating, managing, and publishing Python packages.</p>
<p>It provides an easy-to-use command-line interface for managing dependencies, building packages, and publishing them to <a target="_blank" href="https://pypi.org/">PyPI</a> (Python Package Index), the official repository of Python packages.</p>
<p>There are several benefits of using Poetry for package management in Python:</p>
<ul>
<li><p><strong>Dependency resolution</strong>: It automatically manages dependencies and ensures that your package is compatible with other packages in your project.</p>
</li>
<li><p><strong>Virtual environments</strong>: It creates a virtual environment for your project, which allows you to isolate your package and its dependencies from the rest of your system.</p>
</li>
<li><p><strong>Project scaffolding</strong>: It provides a simple command-line interface for creating new Python projects and setting up their basic structure.</p>
</li>
<li><p><strong>Built-in building and packaging</strong>: It provides tools for creating distributable packages in a variety of formats, including source distributions, wheel distributions, and binary distributions.</p>
</li>
<li><p><strong>Publishing to PyPI</strong>: It makes it easy to publish your package to PyPI, allowing other developers to easily install and use your package.</p>
</li>
</ul>
<p>Overall, Poetry provides a simple and intuitive interface for managing dependencies, building packages, and publishing them to PyPI. If you're working on a Python project that requires package management, Poetry is definitely worth checking out.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow this tutorial, it is recommended that you have the following:</p>
<ul>
<li><p>Python 3.7+ installed</p>
</li>
<li><p>Basic understanding of <a target="_blank" href="https://docs.python.org/3/tutorial/venv.html">virtual environments, modules, and packages</a></p>
</li>
<li><p>Basic knowledge of <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-interact-with-web-services-using-python">Requests</a> and <a target="_blank" href="https://pytest.org/">PyTest</a></p>
</li>
</ul>
<p>You can find the code samples used in this tutorial in <a target="_blank" href="https://github.com/ashutoshkrris/phone-number-validator">this repository</a>.</p>
<h2 id="heading-how-to-set-up-the-project">How to Set Up the Project</h2>
<p>Before you can start building your Python package, you need to set up your development environment. This involves installing Poetry, creating a new project, and configuring the project dependencies.</p>
<h3 id="heading-how-to-install-poetry">How to Install Poetry</h3>
<p>Poetry is a cross-platform package manager and build-tool that can be installed on various operating systems, including Linux, macOS, and Windows.</p>
<p>It has a custom installer that creates a dedicated virtual environment for Poetry, which ensures that it operates independently from the rest of the system. This isolated environment prevents unintentional upgrades or removals of dependencies, allowing Poetry to manage its dependencies more efficiently.</p>
<p>To install Poetry, the first step is to open the terminal or command prompt, depending on the operating system you're using.</p>
<p>For Windows users, open Windows Powershell and execute the following command:</p>
<pre><code class="lang-ps1">(<span class="hljs-built_in">Invoke-WebRequest</span> <span class="hljs-literal">-Uri</span> https://install.python<span class="hljs-literal">-poetry</span>.org <span class="hljs-literal">-UseBasicParsing</span>).Content | py -
</code></pre>
<p>For Linux, macOS, and Windows Subsystem for Linux (WSL) users, open the terminal and run the following command:</p>
<pre><code class="lang-bash">curl -sSL https://install.python-poetry.org | python3 -
</code></pre>
<blockquote>
<p>Note that on some systems, the <code>python</code> command may refer to Python 2 instead of Python 3. To avoid any ambiguity, it is recommended to use the <code>python3</code> binary instead.</p>
</blockquote>
<p>Once the installation process is complete, you can verify if Poetry is installed correctly by executing the following command:</p>
<pre><code class="lang-bash">poetry --version
</code></pre>
<p>If you see output similar to <code>Poetry (version 1.4.1)</code>, your installation is complete and ready to use.</p>
<h3 id="heading-how-to-create-a-new-project">How to Create a New Project</h3>
<p>To create a new Poetry project, you can use the <code>new</code> command followed by the name of the project. For example, if you want to create a package for validating phone numbers, you can use the following command:</p>
<pre><code class="lang-bash">poetry new phone-number-validator
</code></pre>
<p>This will create a new folder called <code>phone-number-validator</code> with the following structure:</p>
<pre><code class="lang-bash">phone-number-validator
├── pyproject.toml
├── README.md
├── phone_number_validator
│   └── __init__.py
└── tests
     └── __init__.py
</code></pre>
<p>The <code>phone-number-validator</code> folder contains two files: <code>pyproject.toml</code> and <a target="_blank" href="http://README.md"><code>README.md</code></a>, as well as two packages: <code>phone_number_validator</code> to store the source code files and <code>tests</code> to store the test files.</p>
<h4 id="heading-understanding-the-pyprojecttoml-file"><strong>Understanding the</strong> <code>pyproject.toml</code> <strong>File</strong></h4>
<p>The <code>pyproject.toml</code> file serves as the configuration file for a Poetry project, containing information about the project and its dependencies. The file has three tables by default – <code>tool.poetry</code>, <code>tool.poetry.dependencies</code>, and <code>build-system</code>.</p>
<pre><code class="lang-toml"><span class="hljs-section">[tool.poetry]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"phone-number-validator"</span>
<span class="hljs-attr">version</span> = <span class="hljs-string">"0.1.0"</span>
<span class="hljs-attr">description</span> = <span class="hljs-string">""</span>
<span class="hljs-attr">authors</span> = [<span class="hljs-string">"Ashutosh Krishna &lt;ashutoshbritish@gmail.com&gt;"</span>]
<span class="hljs-attr">readme</span> = <span class="hljs-string">"README.md"</span>
<span class="hljs-attr">packages</span> = [{include = <span class="hljs-string">"phone_number_validator"</span>}]
</code></pre>
<p>The <code>tool.poetry</code> table in the <code>pyproject.toml</code> file has multiple key/value pairs, with <code>name</code>, <code>version</code>, <code>description</code>, and <code>authors</code> being required while others are optional.</p>
<p>Poetry assumes that a package with the same name as the <a target="_blank" href="http://tool.poetry.name"><code>tool.poetry.name</code></a> specified in the <code>pyproject.toml</code> file is located at the root of the project. But if the package location is different, the packages and their locations can be specified in the <code>tool.poetry.packages</code> key.</p>
<pre><code class="lang-toml"><span class="hljs-section">[tool.poetry.dependencies]</span>
<span class="hljs-attr">python</span> = <span class="hljs-string">"^3.11"</span>
</code></pre>
<p>In the <code>tool.poetry.dependencies</code> table, it is mandatory to declare the Python version for which the package is compatible.</p>
<pre><code class="lang-toml"><span class="hljs-section">[build-system]</span>
<span class="hljs-attr">requires</span> = [<span class="hljs-string">"poetry-core"</span>]
<span class="hljs-attr">build-backend</span> = <span class="hljs-string">"poetry.core.masonry.api"</span>
</code></pre>
<p>The last table, <code>build-system</code>, has two keys – <code>requires</code> and <code>build-backend</code>. The <code>requires</code> key is a list of dependencies required to build the package, while the <code>build-backend</code> key is the Python object used to perform the build process.</p>
<p>TOML is Poetry's preferred configuration format, and starting from version 3.11, Python provides the <code>tomllib</code> module for parsing TOML files.</p>
<p>As of now, the <code>pyproject.toml</code> file looks like <a target="_blank" href="https://github.com/ashutoshkrris/phone-number-validator/blob/c1b69d414437f857742a2009743d8a0d8dbf90b8/pyproject.toml">this</a>.</p>
<h3 id="heading-how-to-create-a-new-virtual-environment">How to Create a New Virtual Environment</h3>
<p>Poetry simplifies the creation of virtual environments for your projects. To create a virtual environment for your <code>phone-number-validator</code> library, navigate to your project directory, and run the <code>env use</code> command:</p>
<pre><code class="lang-bash">poetry env use /full/path/to/python
</code></pre>
<p>The <code>/full/path/to/python</code> specifies the full path to the Python executable.</p>
<p>For example, in MacOS:</p>
<pre><code class="lang-bash">poetry env use /usr/<span class="hljs-built_in">local</span>/bin/python3.11
</code></pre>
<p>In Windows:</p>
<pre><code class="lang-bash">poetry env use <span class="hljs-string">"C:\Users\ashut\AppData\Local\Programs\Python\Python311\python.exe"</span>
</code></pre>
<h3 id="heading-how-to-configure-project-dependencies">How to Configure Project Dependencies</h3>
<p>After setting up your Poetry project, the next step is to install the necessary dependencies.</p>
<p>Since you're going to <a target="_blank" href="https://blog.ashutoshkrris.in/how-to-interact-with-web-services-using-python">interact with an external web service</a>, the first dependency you'll need is <code>requests</code>. To install this dependency, Poetry provides an <code>add</code> command that takes care of installing the package correctly, defining version constraints, and updating the <code>pyproject.toml</code> file with the appropriate information.</p>
<pre><code class="lang-bash">poetry add requests
</code></pre>
<p>Once the dependency is installed, you'll see the dependency added in the <code>tool.poetry.dependencies</code> table in your <code>pyproject.toml</code> file.</p>
<pre><code class="lang-toml"><span class="hljs-section">[tool.poetry.dependencies]</span>
<span class="hljs-attr">python</span> = <span class="hljs-string">"^3.11"</span>
<span class="hljs-attr">requests</span> = <span class="hljs-string">"^2.28.2"</span>
</code></pre>
<h4 id="heading-the-poetrylock-file"><strong>The</strong> <code>poetry.lock</code> <strong>file</strong></h4>
<p>The file <code>poetry.lock</code> serves as a record of all the exact versions of the dependencies used in a project during the installation, removal, or updating of any dependency. It ensures that your project uses the correct versions of dependencies by listing all the packages, their exact versions, and the hashes of their source files.</p>
<p>Once you have installed the <code>requests</code> library, the <a target="_blank" href="https://github.com/ashutoshkrris/phone-number-validator/blob/main/poetry.lock"><code>poetry.lock</code></a> file will be updated to record the exact version and hash of the installed dependency. As you add more dependencies to your project, this file will track all the changes.</p>
<p>It's important to commit the <code>poetry.lock</code> file to your version control when sharing your project, as it ensures that others will be using the same versions of dependencies that you used to build and test your project.</p>
<p>To create a <code>requirements.txt</code> file from the <code>poetry.lock</code> file, you can use the following command:</p>
<pre><code class="lang-bash">poetry <span class="hljs-built_in">export</span> --output requirements.txt
</code></pre>
<h2 id="heading-how-to-develop-the-package">How to Develop the Package</h2>
<p>At this point, you've installed the requests library but your application doesn't do anything yet. In this section, you'll start building the functionality of your application.</p>
<p>To begin, create a new file called <code>validator.py</code> inside the <code>phone_number_validator</code> package and follow along.</p>
<p>In this tutorial, you'll be using <a target="_blank" href="https://blog.ashutoshkrris.in/object-oriented-programming-in-python">Object-Oriented Programming</a> principles to build your application. To get started, create a class called <code>PhoneNumberValidator</code>:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PhoneNumberValidator</span>:</span>
    <span class="hljs-keyword">pass</span>
</code></pre>
<p>Next, you need to create a constructor for the class. By default, we want the user to provide their API key. So the constructor should take an <code>api_key</code> argument. Additionally, the constructor should initialize the <code>api_url</code> attribute to <a target="_blank" href="https://api.numlookupapi.com/v1/validate/"><em>https://api.numlookupapi.com/v1/validate/</em></a>:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PhoneNumberValidator</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, api_key: str</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        self.api_key = api_key
        self.api_url = <span class="hljs-string">"https://api.numlookupapi.com/v1/validate/"</span>
</code></pre>
<p>With this, you have a basic class structure in place. You can now start adding more functionality to the <code>PhoneNumberValidator</code> class.</p>
<p>Next, you need to define a method that the user can use to validate a phone number. This method will be called <code>validate()</code>.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validate</span>(<span class="hljs-params">self, phone_number: str, country_code: str = None</span>) -&gt; bool:</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> phone_number:
        <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Phone Number cannot be empty!"</span>)
    response = self._make_api_call(phone_number, country_code)
    <span class="hljs-keyword">if</span> response.ok:
       <span class="hljs-keyword">return</span> response.json()[<span class="hljs-string">"valid"</span>]
   <span class="hljs-keyword">else</span>:
       response.raise_for_status()
</code></pre>
<p>The method takes two parameters: <code>phone_number</code>, which is a required string parameter, and <code>country_code</code>, which is an optional string parameter with a default value of <code>None</code>. The method returns a boolean value indicating whether or not the phone number is valid.</p>
<p>The method first checks if the <code>phone_number</code> parameter is not empty. If it is empty, a <code>ValueError</code> is raised. Next, the method calls a <code>_make_api_call()</code> method (defined later) with the <code>phone_number</code> and <code>country_code</code> parameters to make an API call to validate the phone number.</p>
<p>If the API call is successful, meaning it returns a 200 status code, the method returns the boolean value of the <code>valid</code> key in the JSON response. If the API call fails, a <code>HTTPError</code> is raised with the status code and message provided by the API response.</p>
<p>Since the above method uses a <code>_make_api_call()</code> to make the API call, let's define this method:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_make_api_call</span>(<span class="hljs-params">self, phone_number: str, country_code: str = None</span>)
    <span class="hljs-title">params</span> = {"<span class="hljs-title">apikey</span>":</span> self.api_key}
    <span class="hljs-keyword">if</span> country_code:
        params[<span class="hljs-string">"country_code"</span>] = country_code
    response = requests.get(self.api_url + phone_number, params=params)
    <span class="hljs-keyword">return</span> response
</code></pre>
<p>The <code>_make_api_call()</code> method is a private method of the <code>PhoneNumberValidator</code> class, which makes an API call to the <a target="_blank" href="https://numlookupapi.com/">NumLookupAPI</a> to validate a phone number.</p>
<p>The method takes two arguments, <code>phone_number</code> (a string representing the phone number to be validated) and <code>country_code</code> (an optional string representing the ISO Alpha 2 Country Code for the phone number).</p>
<p>The method returns a <code>requests.Response</code> object, which contains the response returned by the API call. The <code>params</code> variable is a dictionary containing the API key and, if provided, the country code. The <code>requests.get()</code> method is used to send a GET request to the API with the phone number and parameters.</p>
<p>If the API call is successful, the method returns the response object, which will be further processed by the <code>validate()</code> method. If the API call fails, an exception will be raised with the error message.</p>
<p>Your <code>PhoneNumberValidator</code> class will look like <a target="_blank" href="https://github.com/ashutoshkrris/phone-number-validator/blob/main/phone_number_validator/validator.py">this</a> at this point.</p>
<p>Note: you can learn more about the NumLookupAPI in its <a target="_blank" href="https://numlookupapi.com/docs/validate">official documentation</a> here.</p>
<h3 id="heading-example-usage-of-phonenumbervalidator-class-optional"><strong>Example Usage of</strong> <code>PhoneNumberValidator</code> Class (Optional)</h3>
<p>You have now completed the implementation of the phone number validation functionality. To test your application, you can create a file named <a target="_blank" href="http://main.py"><code>main.py</code></a> in the root directory of your project. Note that this step is optional.</p>
<p>In <a target="_blank" href="http://main.py"><code>main.py</code></a>, you can use the <code>PhoneNumberValidator</code> class by importing it from the <code>phone_number_validator.validator</code> module. Then, you can create an instance of the class by passing your API key as an argument to the constructor.</p>
<p>To get the API Key, sign up for a free account on <a target="_blank" href="https://app.numlookupapi.com/register">NumLookupAPI</a> and copy the key from the dashboard:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-01-181245.png" alt="Screenshot-2023-04-01-181245" /></p>
<p>After that, you can call the <code>validate</code> method on the instance with phone numbers that you want to validate. The <code>validate</code> method returns a Boolean value indicating whether the phone number is valid or not.</p>
<p>Here is an example code snippet for <code>main.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> phone_number_validator.validator <span class="hljs-keyword">import</span> PhoneNumberValidator

validator = PhoneNumberValidator(api_key=<span class="hljs-string">"your-api-key-here"</span>)
is_valid1 = validator.validate(<span class="hljs-string">"+15551234"</span>)
is_valid2= validator.validate(<span class="hljs-string">"+12069220880"</span>)
is_valid3= validator.validate(<span class="hljs-string">"2069220880"</span>, country_code=<span class="hljs-string">"US"</span>)
print(is_valid1)
print(is_valid2)
print(is_valid3)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">False
True
True
</code></pre>
<h2 id="heading-how-to-test-the-package">How to Test the Package</h2>
<p>In this section, you will test the <code>phone_number_validator</code> package using <a target="_blank" href="https://docs.pytest.org/en/7.2.x/">Pytest</a>. Testing is an essential part of software development, as it ensures that our code works as expected and helps catch any potential bugs or issues before they are deployed to production. You will be writing test cases to check the functionality of the <code>PhoneNumberValidator</code> class and its methods.</p>
<h3 id="heading-how-to-install-test-dependencies">How to Install Test Dependencies</h3>
<p>In Poetry, a dependency group is a way to group dependencies. The most common use of dependency groups is to separate development and production dependencies. When installing dependencies, you can choose which dependency group to install.</p>
<p>To install the <code>pytest</code> and <code>requests-mock</code> packages in a group called <code>test</code>, run the following command:</p>
<pre><code class="lang-bash">poetry add pytest requests-mock --group <span class="hljs-built_in">test</span>
</code></pre>
<p>In the above command, you used the <code>--group</code> option to specify the group name, <code>test</code> in this case. After you install the dependencies, your <code>pyproject.toml</code> file looks like the below:</p>
<pre><code class="lang-toml"><span class="hljs-section">[tool.poetry]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"phone-number-validator"</span>
<span class="hljs-attr">version</span> = <span class="hljs-string">"0.1.0"</span>
<span class="hljs-attr">description</span> = <span class="hljs-string">""</span>
<span class="hljs-attr">authors</span> = [<span class="hljs-string">"Ashutosh Krishna &lt;ashutoshbritish@gmail.com&gt;"</span>]
<span class="hljs-attr">readme</span> = <span class="hljs-string">"README.md"</span>
<span class="hljs-attr">packages</span> = [{include = <span class="hljs-string">"phone_number_validator"</span>}]

<span class="hljs-section">[tool.poetry.dependencies]</span>
<span class="hljs-attr">python</span> = <span class="hljs-string">"^3.11"</span>
<span class="hljs-attr">requests</span> = <span class="hljs-string">"^2.28.2"</span>


<span class="hljs-section">[tool.poetry.group.test.dependencies]</span>
<span class="hljs-attr">pytest</span> = <span class="hljs-string">"^7.2.2"</span>
<span class="hljs-attr">requests-mock</span> = <span class="hljs-string">"^1.10.0"</span>

<span class="hljs-section">[build-system]</span>
<span class="hljs-attr">requires</span> = [<span class="hljs-string">"poetry-core"</span>]
<span class="hljs-attr">build-backend</span> = <span class="hljs-string">"poetry.core.masonry.api"</span>
</code></pre>
<h3 id="heading-how-to-write-the-tests">How to Write the Tests</h3>
<p>To recall, you previously created a <code>validate</code> method to validate phone numbers. Now that you have installed the necessary testing environment dependencies, it's time to write the code to test the functionality of your application.</p>
<p>Create a <code>test_validator.py</code> file inside your <code>tests</code> package and add the following code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pytest
<span class="hljs-keyword">from</span> phone_number_validator.validator <span class="hljs-keyword">import</span> PhoneNumberValidator


VALID_PHONE_NUMBER=<span class="hljs-string">"+12069220880"</span>
INVALID_PHONE_NUMBER=<span class="hljs-string">"+15551234"</span>
PHONE_NUMBER_WITHOUT_COUNTRY_CODE=<span class="hljs-string">"2069220880"</span>


<span class="hljs-meta">@pytest.fixture</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validator</span>():</span>
    <span class="hljs-keyword">return</span> PhoneNumberValidator(api_key=<span class="hljs-string">"test_api_key"</span>)
</code></pre>
<p>The code imports the necessary modules for writing the test cases. The <code>@pytest.fixture</code> decorator is used to define a <a target="_blank" href="https://docs.pytest.org/en/6.2.x/fixture.html#">fixture</a> <code>validator()</code> which creates a new instance of the <code>PhoneNumberValidator</code> class with the <code>test_api_key</code> parameter. This fixture can be used in multiple tests to create a new instance of <code>PhoneNumberValidator</code>.</p>
<p>Next, add the following test cases after the fixture:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_valid_phone_number</span>(<span class="hljs-params">validator, requests_mock</span>):</span>
    requests_mock.get(validator.api_url + VALID_PHONE_NUMBER, json={<span class="hljs-string">"valid"</span>: <span class="hljs-literal">True</span>})
    <span class="hljs-keyword">assert</span> validator.validate(VALID_PHONE_NUMBER) == <span class="hljs-literal">True</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_invalid_phone_number</span>(<span class="hljs-params">validator, requests_mock</span>):</span>
    requests_mock.get(validator.api_url + INVALID_PHONE_NUMBER, json={<span class="hljs-string">"valid"</span>: <span class="hljs-literal">False</span>})
    <span class="hljs-keyword">assert</span> validator.validate(INVALID_PHONE_NUMBER) == <span class="hljs-literal">False</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_api_call_failure</span>(<span class="hljs-params">validator, requests_mock</span>):</span>
    requests_mock.get(validator.api_url, status_code=<span class="hljs-number">500</span>)
    <span class="hljs-keyword">with</span> pytest.raises(Exception):
        validator.validate(INVALID_PHONE_NUMBER)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_phone_number_without_country_code</span>(<span class="hljs-params">validator, requests_mock</span>):</span>
    requests_mock.get(
        validator.api_url + PHONE_NUMBER_WITHOUT_COUNTRY_CODE, json={<span class="hljs-string">"valid"</span>: <span class="hljs-literal">True</span>, <span class="hljs-string">"country_code"</span>: <span class="hljs-string">"US"</span>}
    )
    <span class="hljs-keyword">assert</span> validator.validate(PHONE_NUMBER_WITHOUT_COUNTRY_CODE, country_code=<span class="hljs-string">"US"</span>) == <span class="hljs-literal">True</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_phone_number_with_unsupported_country_code</span>(<span class="hljs-params">validator, requests_mock</span>):</span>
    requests_mock.get(validator.api_url, status_code=<span class="hljs-number">400</span>)
    <span class="hljs-keyword">with</span> pytest.raises(Exception):
        validator.validate(VALID_PHONE_NUMBER, country_code=<span class="hljs-string">"ZZ"</span>)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_invalid_api_key</span>(<span class="hljs-params">validator, requests_mock</span>):</span>
    requests_mock.get(validator.api_url, status_code=<span class="hljs-number">401</span>)
    <span class="hljs-keyword">with</span> pytest.raises(Exception):
        validator.validate(VALID_PHONE_NUMBER)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_invalid_phone_number_type</span>(<span class="hljs-params">validator</span>):</span>
    <span class="hljs-keyword">with</span> pytest.raises(TypeError):
        validator.validate(<span class="hljs-number">5551234</span>)


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_empty_phone_number</span>(<span class="hljs-params">validator</span>):</span>
    <span class="hljs-keyword">with</span> pytest.raises(ValueError):
        validator.validate(<span class="hljs-string">""</span>)
</code></pre>
<p>Each test function defines a scenario that tests whether the <code>validate()</code> method works correctly for a given input. The test cases cover the following scenarios:</p>
<ol>
<li><p><code>test_valid_phone_number</code>: This test case checks if the <code>validate</code> method returns <code>True</code> for a valid phone number. The phone number used for this test is <code>+12069220880</code>, and the response from the API is mocked to return <code>{"valid": True}</code>.</p>
</li>
<li><p><code>test_invalid_phone_number</code>: This test case checks if the <code>validate</code> method returns <code>False</code> for an invalid phone number. The phone number used for this test is <code>+15551234</code>, and the response from the API is mocked to return <code>{"valid": False}</code>.</p>
</li>
<li><p><code>test_api_call_failure</code>: This test case checks if an exception is raised when there is a failure in making an API call. The phone number used for this test is an invalid phone number (<code>+15551234</code>), and the API call is mocked to return a status code of <code>500</code>.</p>
</li>
<li><p><code>test_phone_number_without_country_code</code>: This test case checks if the <code>validate</code> method can validate a phone number without a country code, by specifying the country code as an argument. The phone number used for this test is <code>2069220880</code>, and the response from the API is mocked to return <code>{"valid": True, "country_code": "US"}</code>.</p>
</li>
<li><p><code>test_phone_number_with_unsupported_country_code</code>: This test case checks if an exception is raised when an unsupported country code is specified. The phone number used for this test is a valid phone number (<code>+12069220880</code>), and the API call is mocked to return a status code of <code>400</code>.</p>
</li>
<li><p><code>test_invalid_api_key</code>: This test case checks if an exception is raised when an invalid API key is used. The phone number used for this test is a valid phone number (<code>+12069220880</code>), and the API call is mocked to return a status code of <code>401</code>.</p>
</li>
<li><p><code>test_invalid_phone_number_type</code>: This test case checks if an exception is raised when the phone number passed to the <code>validate</code> method is not a string.</p>
</li>
<li><p><code>test_empty_phone_number</code>: This test case checks if an exception is raised when an empty string is passed as the phone number to the <code>validate</code> method.</p>
</li>
</ol>
<p>Your <code>test_validator.py</code> file should look like <a target="_blank" href="https://github.com/ashutoshkrris/phone-number-validator/blob/main/tests/test_validator.py">this</a> at this point.</p>
<p>To run the tests, it is important to execute the <code>pytest</code> command inside the virtual environment. Poetry provides a <code>run</code> command to execute the given command inside the project’s virtual environment. So execute the following command to run the tests:</p>
<pre><code class="lang-bash">poetry run pytest -v
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">poetry run pytest -v
============================================== <span class="hljs-built_in">test</span> session starts ===============================================
platform win32 -- Python 3.11.0, pytest-7.2.2, pluggy-1.0.0 -- C:\Users\ashut\AppData\Local\pypoetry\Cache\virtualenvs\phone-number-validator-j1Sa98gs-py3.11\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\Blog-Codes\phone-number-validator
plugins: requests-mock-1.10.0
collected 8 items

tests/test_validator.py::test_valid_phone_number PASSED                                                     [ 12%] 
tests/test_validator.py::test_invalid_phone_number PASSED                                                   [ 25%] 
tests/test_validator.py::test_api_call_failure PASSED                                                       [ 37%] 
tests/test_validator.py::test_phone_number_without_country_code PASSED                                      [ 50%]
tests/test_validator.py::test_phone_number_with_unsupported_country_code PASSED                             [ 62%] 
tests/test_validator.py::test_invalid_api_key PASSED                                                        [ 75%] 
tests/test_validator.py::test_invalid_phone_number_type PASSED                                              [ 87%] 
tests/test_validator.py::test_empty_phone_number PASSED                                                     [100%] 

=============================================== 8 passed <span class="hljs-keyword">in</span> 0.05s ================================================
</code></pre>
<h2 id="heading-how-to-publish-the-package">How to Publish the Package</h2>
<p>At this point in your project, you have created a library that can validate phone numbers and you've written test cases to ensure its functionality.</p>
<p>If you want to make this library available to others, you can publish it online. Poetry provides a straightforward way to publish a package using the publish command.</p>
<p>But before you can publish your library, you need to package it with the build command:</p>
<pre><code class="lang-bash">poetry build
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Building phone-number-validator (0.1.0)
  - Building sdist
  - Built phone_number_validator-0.1.0.tar.gz
  - Building wheel
  - Built phone_number_validator-0.1.0-py3-none-any.whl
</code></pre>
<p>Packaging a project before publishing is a crucial step, as it simplifies the process of distribution, installation, and usage for others.</p>
<p>Poetry uses the information specified in the <code>pyproject.toml</code> file such as project name, version, and dependencies to package the project in two different formats – sdist and wheel. The wheel distributions are pre-compiled packages that can be installed quickly, whereas source distributions contain the raw source code and require compilation.</p>
<p>To publish your library, you will need to <a target="_blank" href="https://python-poetry.org/docs/repositories/#configuring-credentials">properly configure your PyPI credentials</a>, as Poetry will publish the library to PyPI by default.</p>
<p>Once the library is packaged, you can use the <code>publish</code> command to publish it.</p>
<pre><code class="lang-bash">poetry publish
</code></pre>
<p>After executing the <code>poetry publish</code> command, your package will be published on the Python Package Index (PyPI), which makes it available for installation through Poetry.</p>
<p>Output:</p>
<pre><code class="lang-bash">Publishing phone-number-validator (0.1.0) to PyPI
 - Uploading phone_number_validator-0.1.0-py3-none-any.whl 0%
 - Uploading phone_number_validator-0.1.0-py3-none-any.whl 100%
 - Uploading phone_number_validator-0.1.0.tar.gz 0%
 - Uploading phone_number_validator-0.1.0.tar.gz 100%
</code></pre>
<p>Once the package is published, it can be searched on PyPI. For instance, you can search for the <a target="_blank" href="https://pypi.org/project/phone-number-validator/"><code>phone-number-validator</code></a> library on PyPI. After finding it, you can install it on your system and try using it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-03-212242.png" alt="Screenshot-2023-04-03-212242" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, I explained how Poetry works and how to use its features. You have learned how to create a new Poetry project, manage dependencies, and handle versioning. You have also learned how to write and run tests using Pytest, and package and publish your Python library on PyPI using Poetry.</p>
<p>By following this tutorial, you now have the skills needed to create, manage, and distribute your own Python packages with ease. With further exploration and practice, you can expand your knowledge of Poetry and use it to develop and share your own Python libraries for others to use.</p>
<p>If you've followed along with this tutorial and built your package, I encourage you to share your creation with the world! Take a screenshot or record a video of your application in action, and share it on Twitter. Be sure to tag me, <a target="_blank" href="https://twitter.com/ashutoshkrris">@ashutoshkrris</a>, so that I can see your work and share it with my followers.</p>
<p>I can't wait to see what you've created! Happy coding!</p>
<h3 id="heading-additional-resources"><strong>Additional Resources</strong></h3>
<ul>
<li><p><a target="_blank" href="https://github.com/ashutoshkrris/phone-number-validator">Github repository</a> for the tutorial</p>
</li>
<li><p><a target="_blank" href="https://blog.ashutoshkrris.in/how-to-interact-with-web-services-using-python">How to interact with web services in Python</a></p>
</li>
<li><p><a target="_blank" href="https://numlookupapi.com/docs/">NumLookupAPI Documentation</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Mastering List Destructuring and Packing in Python: A Comprehensive Guide]]></title><description><![CDATA[List destructuring, also known as packing and unpacking, is a powerful technique in Python for assigning and manipulating lists. It allows you to quickly assign values from a list to multiple variables, as well as easily extract values from complex n...]]></description><link>https://blog.ashutoshkrris.in/mastering-list-destructuring-and-packing-in-python-a-comprehensive-guide</link><guid isPermaLink="true">https://blog.ashutoshkrris.in/mastering-list-destructuring-and-packing-in-python-a-comprehensive-guide</guid><category><![CDATA[Python]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Ashutosh Krishna]]></dc:creator><pubDate>Sat, 25 Mar 2023 10:11:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679739096011/d0ef25d9-b15d-4e3b-8aca-280b8a8b3c3e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>List destructuring, also known as packing and unpacking, is a powerful technique in Python for assigning and manipulating lists. It allows you to quickly assign values from a list to multiple variables, as well as easily extract values from complex nested lists. This technique is widely used in Python programming and is an important tool for improving code readability and reducing the amount of code required for complex operations.</p>
<p>In this tutorial, you will explore the concepts of list destructuring and learn how to use them effectively in your Python code. By the end of this tutorial, you will have a solid understanding of list destructuring and be able to use it effectively in your own Python programs.</p>
<h2 id="heading-destructuring-assignment">Destructuring Assignment</h2>
<p>Destructuring assignment is a powerful feature in Python that allows you to unpack values from iterable, such as lists, tuples, and strings, and assign them to variables in a single line of code. This makes it easy to extract specific values from complex data structures and assign them to variables for further use. It's also known as <strong>unpacking</strong> because you are unpacking the values from the iterable.</p>
<h3 id="heading-destructuring-as-values">Destructuring as Values</h3>
<p>One way to use destructuring assignment is to unpack values from an iterable and assign them to variables. This is done by adding the variables to be assigned on the left-hand side of the assignment operator, and the iterable containing the values to be unpacked on the right-hand side. For example:</p>
<pre><code class="lang-python">x, y, z = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
print(x, y, z)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">1 2 3
</code></pre>
<p>Here, you unpack the values 1, 2, and 3 from the list <code>[1, 2, 3]</code> and assign them to variables <code>x</code>, <code>y</code>, and <code>z</code>, respectively. You can then use these variables elsewhere in your code.</p>
<p>If you try to unpack more values than the length of the iterable, you will get a <strong>ValueError: not enough values to unpack</strong> error. For example:</p>
<pre><code class="lang-python">x, y, z = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">x, y, z = [1, 2]
    ^^^^^^^
ValueError: not enough values to unpack (expected 3, got 2)
</code></pre>
<blockquote>
<p>Note: The error message may differ according to the Python version. But the error will surely be a ValueError.</p>
</blockquote>
<h3 id="heading-destructuring-as-list">Destructuring as List</h3>
<p>Another way to use destructuring assignment is to unpack values from an iterable and assign them to a list. To do so, you can first assign the values to the variables you want. You can then use the asterisk (*) operator to assign the remaining values in an iterable to a list. For example:</p>
<pre><code class="lang-python">x, y, *rest = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
print(x)
print(y)
print(rest)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">1
2
[3, 4, 5]
</code></pre>
<p>In this example, you assign the first two values of the list to the variables <code>x</code> and <code>y</code>, and then use the asterisk operator to assign the remaining values to the list <code>rest</code>.</p>
<p>The above code sample is equivalent to:</p>
<pre><code class="lang-python">nums = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]

print(nums[<span class="hljs-number">0</span>])
print(nums[<span class="hljs-number">1</span>])
print(nums[<span class="hljs-number">2</span>:])
</code></pre>
<h3 id="heading-ignoring-values-in-destructuring-assignments">Ignoring Values in Destructuring Assignments</h3>
<p>Sometimes, you may only be interested in unpacking certain values from an iterable and want to ignore the rest. You can do this using an underscore (_) as a placeholder for the values you want to ignore. For example:</p>
<pre><code class="lang-python">x, _, z = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
print(x, z)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">1 3
</code></pre>
<p>In the above example, you use the underscore character to ignore the second value of the list. It's worth noting that although the underscore character is often used as a placeholder, it can be used as a variable name like any other valid variable name in Python. However, most people do not use it as a variable and instead use it solely as a placeholder when they want to ignore a value in a destructuring assignment.</p>
<h3 id="heading-ignoring-lists-in-destructuring-assignments">Ignoring Lists in Destructuring Assignments</h3>
<p>You can ignore many values using the *_ syntax. For example:</p>
<pre><code class="lang-python">x, *_ = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
print(x)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">1
</code></pre>
<p>Here, you assign the first value of the list to the variable <code>x</code> and ignore the rest of the values using the *_ syntax. In this case, the value of <code>x</code> is 1 and the rest of the values are ignored. This technique can be useful when you are only interested in the first value of an iterable and don't need to use the remaining values.</p>
<p>However, the above example isn't interesting as you could have just used indexing to extract the first value. It becomes interesting in scenarios where you intend to retain the first and last values during an assignment. For example:</p>
<pre><code class="lang-python">x, *_, y = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
print(x, y)

<span class="hljs-comment"># Output: 1 5</span>
</code></pre>
<p>Alternatively, when you need to extract several values at once:</p>
<pre><code class="lang-python">x, _, y, _, z, *_ = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]
print(x, y, z)

<span class="hljs-comment"># Output: 1 3 5</span>
</code></pre>
<h2 id="heading-packing-function-arguments">Packing Function Arguments</h2>
<p>In functions, you can define a number of mandatory arguments which will make the function callable only when all the arguments are provided.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func</span>(<span class="hljs-params">arg1, arg2, arg3</span>):</span>
    <span class="hljs-keyword">return</span> arg1, arg2, arg3

func()
</code></pre>
<p>If you don't pass the arguments, you get the following error:</p>
<pre><code class="lang-bash">TypeError: func() missing 3 required positional arguments: <span class="hljs-string">'arg1'</span>, <span class="hljs-string">'arg2'</span>, and <span class="hljs-string">'arg3'</span>
</code></pre>
<p>You can also define arguments as optional by using default values. This allows you to call the function in different ways depending on which arguments you want to provide.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func</span>(<span class="hljs-params">arg1=<span class="hljs-string">'a'</span>, arg2=<span class="hljs-number">1</span>, arg3=[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]</span>):</span>
    <span class="hljs-keyword">return</span> arg1, arg2, arg3

func()
func(<span class="hljs-string">'b'</span>)
func(<span class="hljs-string">'c'</span>, <span class="hljs-number">2</span>)
func(<span class="hljs-string">'d'</span>, <span class="hljs-number">3</span>, [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>])
...
</code></pre>
<p>In this section, you'll explore how to pack arguments in Python using the destructuring syntax. Packing arguments involves passing a variable number of arguments to a function, which can then be accessed as a single variable within the function. There are several ways to pack arguments in Python, including packing a list of arguments and packing keyword arguments. Let's dive in!</p>
<h3 id="heading-packing-a-list-of-arguments">Packing a List of Arguments</h3>
<p>We can pack values into a list using the <code>*</code> operator. When the function is called, the <code>*</code> operator unpacks the values in the list and passes them as separate arguments to the function. Here's an example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_numbers</span>(<span class="hljs-params">a, b, c</span>):</span>
    <span class="hljs-keyword">return</span> a + b + c

values = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
result = add_numbers(*values)
print(result)
print(add_numbers(*[<span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]))
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">6
12
</code></pre>
<p>In this example, you define a function <code>add_numbers</code> that takes three arguments and returns their sum. You then define a list of values <code>values</code> containing the values we want to pass as arguments to the function. When you call the function using <code>add_numbers(*values)</code>, the values in the list are unpacked and passed as separate arguments to the function.</p>
<p>You can also use the unpacking operator to directly pass a list to a function without creating a separate variable as seen on the last line of the code.</p>
<p>Note that the number of values in the list must match the number of arguments expected by the function. If we try to pass too many or too few values, a <code>TypeError</code> will be raised:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_numbers</span>(<span class="hljs-params">a, b, c</span>):</span>
    <span class="hljs-keyword">return</span> a + b + c

values = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
result = add_numbers(*values)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">result = add_numbers(*values)
             ^^^^^^^^^^^^^^^^^^^^
TypeError: add_numbers() missing 1 required positional argument: <span class="hljs-string">'c'</span>
</code></pre>
<h3 id="heading-packing-keyword-arguments">Packing Keyword Arguments</h3>
<p>You can also pack keyword arguments into a dictionary using the <code>**</code> operator. When the function is called, the <code>**</code> operator unpacks the dictionary and passes the key-value pairs as separate keyword arguments to the function. Here's an example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_numbers</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x * y

kwargs = {<span class="hljs-string">'x'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'y'</span>: <span class="hljs-number">3</span>}
result = multiply_numbers(**kwargs)
print(result)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">6
</code></pre>
<p>In this example, you define a function <code>multiply_numbers</code> that takes two keyword arguments and returns their product. You then define a dictionary <code>kwargs</code> containing the key-value pairs we want to pass as keyword arguments to the function. When you call the function using <code>multiply_numbers(**kwargs)</code>, the dictionary is unpacked and the key-value pairs are passed as separate keyword arguments to the function.</p>
<p>Note that the keys in the dictionary must match the names of the keyword arguments expected by the function. If you try to pass a key that doesn't match a keyword argument name, a <code>TypeError</code> will be raised:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_numbers</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x * y

kwargs = {<span class="hljs-string">'a'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'b'</span>: <span class="hljs-number">3</span>}
result = multiply_numbers(**kwargs)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">result = multiply_numbers(**kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: multiply_numbers() got an unexpected keyword argument <span class="hljs-string">'a'</span>
</code></pre>
<p>Similarly, if you try to pass a keyword argument that the function doesn't expect, a <code>TypeError</code> will be raised:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">multiply_numbers</span>(<span class="hljs-params">x, y</span>):</span>
    <span class="hljs-keyword">return</span> x * y

kwargs = {<span class="hljs-string">'x'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'y'</span>: <span class="hljs-number">3</span>, <span class="hljs-string">'z'</span>: <span class="hljs-number">4</span>}
result = multiply_numbers(**kwargs)
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">result = multiply_numbers(**kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: multiply_numbers() got an unexpected keyword argument <span class="hljs-string">'z'</span>
</code></pre>
<h2 id="heading-unpacking-functional-arguments">Unpacking Functional Arguments</h2>
<p>In Python, you can create a function that can accept any number of arguments, without enforcing their position or name at "compile" time. This is achieved by using special parameters, *args and **kwargs.</p>
<p>Here's an example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_function</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
    print(args, kwargs)
</code></pre>
<p>The <code>*args</code> parameter is set to a tuple and the <code>**kwargs</code> parameter is set to a dictionary. When you call the function, any positional arguments will be gathered into <code>args</code>, and any keyword arguments will be gathered into <code>kwargs</code>.</p>
<p>Here are some examples of how you can call the function:</p>
<pre><code class="lang-python">my_function(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
<span class="hljs-comment"># Output: (1, 2, 3) {}</span>

my_function(a=<span class="hljs-number">1</span>, b=<span class="hljs-number">2</span>, c=<span class="hljs-number">3</span>)
<span class="hljs-comment"># Output: () {'a': 1, 'b': 2, 'c': 3}</span>

my_function(<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>, <span class="hljs-string">'z'</span>, a=<span class="hljs-number">1</span>, b=<span class="hljs-number">2</span>, c=<span class="hljs-number">3</span>)
<span class="hljs-comment"># Output: ('x', 'y', 'z') {'a': 1, 'b': 2, 'c': 3}</span>
</code></pre>
<p>The <code>*args</code> and <code>**kwargs</code> parameters are commonly used when passing arguments to another function. For example, you might want to extend the string class by creating a new class that inherits from <code>str</code>:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyList</span>(<span class="hljs-params">list</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, *args, **kwargs</span>):</span>
        print(<span class="hljs-string">'Constructing MyList'</span>)
        super(MyList, self).__init__(*args, **kwargs)

my_list = MyList([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
print(my_list)
</code></pre>
<p>In this example, you're defining a new class <code>MyList</code> that inherits from the built-in <code>list</code> class. You're overriding the <code>__init__</code> method to print a message and then calling the parent class's <code>__init__</code> method using <code>super()</code>. Finally, you create a new instance of <code>MyList</code> by passing in a list of integers and printing the resulting object. This will output:</p>
<pre><code class="lang-bash">Constructing MyList
[1, 2, 3]
</code></pre>
<p>You can learn more about *args and **kwargs in <a target="_blank" href="https://blog.ashutoshkrris.in/args-and-kwargs-in-python">this tutorial</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>List destructuring is a powerful feature in Python that allows for the unpacking of values from an iterable and assigning them to variables. It enables developers to easily manipulate and work with data structures such as lists, tuples, and dictionaries. Additionally, the ability to pack and unpack function arguments provides a flexible and convenient way to handle function parameters, allowing for more dynamic and versatile code. By understanding these concepts and techniques, Python developers can write cleaner and more efficient code, making their programming experience more enjoyable and productive.</p>
]]></content:encoded></item></channel></rss>