<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Brilian Firdaus</title>
    <description>The latest articles on DEV Community by Brilian Firdaus (@brilianfird).</description>
    <link>https://dev.to/brilianfird</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F518669%2F752abdc9-3ef8-42e3-9e7e-632a9892fcb2.jpeg</url>
      <title>DEV Community: Brilian Firdaus</title>
      <link>https://dev.to/brilianfird</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brilianfird"/>
    <language>en</language>
    <item>
      <title>Understanding Database Locks: Managing Concurrency in Databases</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Wed, 23 Apr 2025 15:25:21 +0000</pubDate>
      <link>https://dev.to/brilianfird/understanding-database-locks-managing-concurrency-in-databases-334i</link>
      <guid>https://dev.to/brilianfird/understanding-database-locks-managing-concurrency-in-databases-334i</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4dg2itvx3oyn6kkq8bb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4dg2itvx3oyn6kkq8bb6.png" alt="Understanding Database Locks: Managing Concurrency in Databases&amp;lt;br&amp;gt;
" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consistency in a database is crucial when building a system that serve many users. Imagine maintaining a concert booking system, and a very famous artist has just started selling assigned seats to the concert. Many people start purchasing seats as soon as the selling time begins. What you don't want to happen in this case is for seats to be oversold, resulting in more than one person being assigned to a single seat. This could cause a disaster at the event as people might fight for their seats, ultimately damaging your reputation as the person managing the booking system.&lt;/p&gt;

&lt;p&gt;In this article, we will explore how concurrency works in databases and how to prevent the scenario mentioned earlier from happening. We'll cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Why Databases Use Locks&lt;/strong&gt; : We'll delve more thoroughly into the previous example to understand what's happening and why database locks can prevent such issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Lock and Exclusive Lock&lt;/strong&gt; : There are two types of locks based on how they lock processes. We'll learn about them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read Phenomenon and Isolation Levels&lt;/strong&gt; : The more consistency you want in your database, the stricter the database lock process will be. Inconsistent reading in a database is known as a read phenomenon, and it can be managed by adjusting the isolation level of a database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Types of Locks&lt;/strong&gt; : We'll check out different types of database locks, how they behave, and when to use them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ℹ️ This article focuses on SQL databases. Not all concepts are applicable to their NoSQL counterparts.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Databases Use Locks
&lt;/h2&gt;

&lt;p&gt;For starters, let's explore our concert booking system and break down how race conditions can occur. Suppose we have the following simplified schema for the database:&lt;/p&gt;

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

&lt;p&gt;Let's create a simplified query of how we can book the seat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN;
SELECT * FROM seats WHERE id = '1';
UPDATE seats SET remainingQty = remainingQty - 1 WHERE id = '1';
COMMIT;

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

&lt;/div&gt;



&lt;p&gt;💡&lt;code&gt;BEGIN;&lt;/code&gt; and &lt;code&gt;COMMIT;&lt;/code&gt; are SQL command that indicates when the transaction started and ended. The SQL database will ensure that the operations between them are executed atomically.&lt;/p&gt;

&lt;p&gt;Now let's see how the transaction would work if there are concurrent processes operating on the same row:&lt;/p&gt;

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

&lt;p&gt;As you can see, there are two different processes working on the same row. As a result, both processes will indicate that their respective booking is successful. The seat that only had one available spot now has multiple bookings.&lt;/p&gt;

&lt;p&gt;This issue is called a  &lt;strong&gt;race condition&lt;/strong&gt; , and it's a common problem in multi-threaded applications. Thankfully, databases have a built-in locking mechanism to prevent this from happening.&lt;/p&gt;

&lt;p&gt;Moving forward, we'll explore how the database locks work. At the end of the article, we'll figure out how to solve the concert booking example (note: it's actually quite simple).&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared and Exclusive Lock
&lt;/h2&gt;

&lt;p&gt;There are two types of database locks related to their functionality:  &lt;strong&gt;Shared Lock&lt;/strong&gt;  and  &lt;strong&gt;Exclusive Lock&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;When a row is locked with a  &lt;strong&gt;Shared Lock&lt;/strong&gt; , other transactions are prevented from writing to that row. This lock is typically used when a transaction is reading a specific row and needs to ensure that the data remains consistent throughout the transaction. Multiple transactions can hold a shared lock on the same row simultaneously, but no transaction can modify the row while it's locked in shared mode.&lt;/p&gt;

&lt;p&gt;On the other hand, an  &lt;strong&gt;Exclusive Lock&lt;/strong&gt;  locks the row for both reading and writing processes. Typically, when a transaction is writing to a row, it will place an exclusive lock on that row. This lock ensures that other transactions cannot read or write to the row while it is being modified. The exclusive lock ensures complete isolation of the transaction, maintaining data integrity by preventing concurrent access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read Phenomenon and Isolation Level
&lt;/h2&gt;

&lt;p&gt;When reading data from a database, you can encounter inconsistent data due to concurrent processes working on the same data. This is known as a  &lt;strong&gt;Read Phenomenon&lt;/strong&gt;. Various read phenomena range from simple to more complex. To tackle this issue, databases allow you to set the  &lt;strong&gt;Isolation Level&lt;/strong&gt;  for each transaction. The stricter the isolation level, the fewer read phenomena that can occur, but this may also slow down your database. This is because stricter isolation levels involve more complex locking mechanisms.&lt;/p&gt;

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

&lt;p&gt;It is important to note that isolation levels can vary between SQL databases. To make the topic easier to understand, we will explore the simplest isolation level mechanisms that uses only &lt;strong&gt;Pessimistic Locking&lt;/strong&gt; (we'll also explore the others in the next section).&lt;/p&gt;

&lt;h3&gt;
  
  
  Read Uncommitted
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Read Uncommitted&lt;/strong&gt;  is the most lenient isolation level. At this level, there is no locking mechanism at all. This means that, as the name suggests, a transaction can read data from another transaction that has not yet been committed.&lt;/p&gt;

&lt;p&gt;Although this is the fastest isolation level, it can cause issues when a transaction reads data from an uncommitted transaction that is later rolled back. This phenomenon is known as  &lt;strong&gt;Dirty Reads&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The previously mentioned  &lt;strong&gt;Race Condition&lt;/strong&gt;  example can also occur due to this level of isolation. Because of the high inconsistency that can happen with this isolation level, some databases, like PostgreSQL, choose not to support it at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read Committed
&lt;/h3&gt;

&lt;p&gt;The next isolation level is  &lt;strong&gt;Read Committed&lt;/strong&gt;. As the name suggests, at this level, the database will only allow transactions to read data that has been committed.&lt;/p&gt;

&lt;p&gt;Starting at this isolation level, your transaction is prevented from reading data from another unfinished transaction. To achieve this, the database places an exclusive lock when a transaction is writing to a row, ensuring that other transactions cannot read or write to it until the transaction is completed.&lt;/p&gt;

&lt;p&gt;Now, let's consider what could happen when you read from the same row twice within the same transaction:&lt;/p&gt;

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

&lt;p&gt;This phenomenon is called a  &lt;strong&gt;Non-Repeatable Read&lt;/strong&gt;. It occurs when a transaction reads the same row twice and gets different results each time, because another transaction has committed changes to the row in between the reads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repeatable Read
&lt;/h3&gt;

&lt;p&gt;To combat the  &lt;strong&gt;Non-Repeatable Read&lt;/strong&gt;  phenomenon, we can use the  &lt;strong&gt;Repeatable Read&lt;/strong&gt;  isolation level. In this isolation level, your transaction will also place a shared lock on the rows you're working on. This means that if another transaction attempts to update the data before your transaction is completed, it will be blocked. This isolation level ensures that your transaction always reads the same value from a row throughout its execution.&lt;/p&gt;

&lt;p&gt;However, this isolation level cannot handle a read phenomenon called  &lt;strong&gt;Phantom Read&lt;/strong&gt;. Phantom reads occur when you read a set of rows, and then another transaction inserts new rows that satisfy the criteria of your previous query. As a result, if you rerun the same query, the new rows (phantoms) will appear in the result set.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serializable
&lt;/h3&gt;

&lt;p&gt;The last isolation level we'll explore is  &lt;strong&gt;Serializable&lt;/strong&gt; , which is the strictest isolation level. In the Serializable isolation level, the database ensures that transactions run as if they were executed sequentially, one after the other. This means that effectively, only one transaction can modify data at a time, eliminating any chance of concurrency-related issues.&lt;/p&gt;

&lt;p&gt;By ensuring transactions run in this highly isolated manner, the Serializable isolation level guarantees consistency. Transactions cannot interfere with each other, preventing all types of read phenomena.&lt;/p&gt;

&lt;p&gt;However, this isolation level has a significant drawback: the elimination of concurrency. As a result, the database operations become much slower. The performance trade-off is substantial, as the database throughput is dramatically reduced when ensuring that transactions operate in a serial order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Database Locks
&lt;/h2&gt;

&lt;p&gt;We've explored isolation levels and read phenomena, but we have only scratched the surface of what database locks are. The examples we used before rely on a mechanism called  &lt;strong&gt;Pessimistic Locking&lt;/strong&gt;. However, there are two other approaches to handling database concurrency:  &lt;strong&gt;Optimistic Locking&lt;/strong&gt;  and &lt;strong&gt;MVCC (Multi-Version Concurrency Control)&lt;/strong&gt;. Databases and application frameworks usually use a combination of these locks to handle concurrent processes effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pessimistic Locking
&lt;/h3&gt;

&lt;p&gt;Pessimistic locking is the locking mechanism we explored previously. It behaves such that when a transaction is currently modifying a specific row, another transaction must wait for the change to finish before it can modify the same row.&lt;/p&gt;

&lt;p&gt;One important aspect of pessimistic locking is the potential for  &lt;strong&gt;deadlocks&lt;/strong&gt;. Deadlocks occur when two transactions are each waiting for the other to release a lock on different rows, resulting in both transactions being blocked indefinitely. To handle this, databases typically implement a timeout mechanism. If a transaction cannot acquire the necessary locks within the specified timeout period, the transaction is rolled back, and an error is generated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimistic Locking
&lt;/h3&gt;

&lt;p&gt;Optimistic locking is a type of locking that will fail a transaction if there's another transaction that has already modified the data.&lt;/p&gt;

&lt;p&gt;You can implement optimistic locking by adding version field to your data. When you want to update a row, you'll first retrieve the row to get the version number. Then, you'll include the version number in your update filter. If no row is updated, it means another transaction has already modified that row, and you can conclude that your transaction has failed.&lt;/p&gt;

&lt;p&gt;This also works for consistently reading a row twice (Repeatable Read). First, you need to snapshot the version number from the initial query. For subsequent queries, you'll include the version number or timestamp. If the query doesn't return anything, it means another transaction has already updated the row, and you should rollback the transaction.&lt;/p&gt;

&lt;p&gt;Unlike pessimistic locking, optimistic locking can't cause deadlocks, so it is considered safer. However, you'll need a retry mechanism for writing to your database if you expect concurrent updates on the same row.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Version Concurrency Control
&lt;/h3&gt;

&lt;p&gt;In Multi-Version Concurrency Control, or for short MVCC, your application will store multiple versions of a row. When you read from the row, your transaction will snapshot the version of the row. This process ensures that you will always get the same result, even if other transactions successfully update the row, because they will create a new version.&lt;/p&gt;

&lt;p&gt;Unlike optimistic locking, your query won't actually return an error when you try to read an outdated version. The database can still return data because it stores multiple versions of the row.&lt;/p&gt;

&lt;p&gt;MVCC handles write concurrency similarly to optimistic locking: it throws an error and rolls back the transaction that tries to write to a row with a newer version or timestamp.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving The Booking Cinema Issue
&lt;/h2&gt;

&lt;p&gt;Let's revisit our first example: how do we solve the issue of overbooking seats in a cncert? The solution is quite simple. The easiest way to keep the query performant is to use the  &lt;strong&gt;Read Committed&lt;/strong&gt;  isolation level with some additions to the query.&lt;/p&gt;

&lt;p&gt;The Read Committed isolation level ensures that no concurrent process is writing to the same row. Next, we'll add a filter to our query, &lt;code&gt;remainingQty &amp;gt;= 1&lt;/code&gt;, which will ensure that there is always at least one seat available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UPDATE seats SET remainingQty = remainingQty - 1 WHERE id = '1' AND remainingQty &amp;gt;= 1;

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

&lt;/div&gt;



&lt;p&gt;To validate whether the transaction is successful, we can count how many rows are affected by the query. If it’s &lt;code&gt;1&lt;/code&gt;, then the query is successful. If it’s &lt;code&gt;0&lt;/code&gt;, then it’s not, and we should throw an error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;In this article, we've explored the types of database locks and how they work. One important reminder is that we have only covered the concepts. Every database system has its own interpretation and implementation of these concepts, and understanding them is crucial if you want to master that specific database. However, the concepts discussed in this article should provide a solid foundation and make it easier for you to understand these implementations.&lt;/p&gt;

</description>
      <category>database</category>
    </item>
    <item>
      <title>A Developer’s Guide to Circuit Breakers: Protect Your Service from Failure</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Mon, 14 Apr 2025 06:00:06 +0000</pubDate>
      <link>https://dev.to/brilianfird/a-developers-guide-to-circuit-breakers-protect-your-service-from-failure-5bf8</link>
      <guid>https://dev.to/brilianfird/a-developers-guide-to-circuit-breakers-protect-your-service-from-failure-5bf8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0y96infoz4ei7q6daou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0y96infoz4ei7q6daou.png" alt="A Developer’s Guide to Circuit Breakers: Protect Your Service from Failure" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you're building complex microservices that handle a lot of traffic, failure becomes a normal part of the system—especially in environments where teams push changes weekly, or even multiple times a week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resiliency&lt;/strong&gt; plays a critical role in software design. A resilient system can isolate failures and recover gracefully. Take a travel commerce example: if one airline's server goes down, that failure shouldn't impact other unrelated flows. Ideally, the system should recover on its own.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Circuit Breaker&lt;/strong&gt; is a commonly used mechanism to improve a system’s resiliency. Inspired by electrical circuit breakers, it behaves similarly—in electricity, when a breaker detects a voltage spike, it trips and stops the current to protect appliances. In software, when a downstream service behaves abnormally, a circuit breaker can trip and stop requests from going through.&lt;/p&gt;

&lt;p&gt;This behavior provides two main benefits: &lt;strong&gt;containing the incident&lt;/strong&gt; to only the affected part of the system and &lt;strong&gt;supporting self-healing&lt;/strong&gt;. In this article, we’ll cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Understanding the Circuit Breaker&lt;/strong&gt; : A deeper look into what it is and how it prevents cascading failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why Use a Circuit Breaker&lt;/strong&gt; : When and why to implement one in your architecture.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How Circuit Breakers Work&lt;/strong&gt; : The internal states and configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementing a Circuit Breaker&lt;/strong&gt; : A hands-on example using Hystrix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Practices&lt;/strong&gt; : Practical tips and gotchas to watch out for.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Understanding The Circuit Breaker
&lt;/h2&gt;

&lt;p&gt;As mentioned, a circuit breaker works like an electrical circuit breaker—it stops traffic to a failing downstream dependency. This is especially helpful when your service has multiple downstream dependencies and flows that are unrelated. If one dependency fails, you don’t want the others to be affected. Circuit breakers help by cutting off the connection entirely, saving resources.&lt;/p&gt;

&lt;p&gt;Think of a building’s electrical system: if there’s a voltage spike, the breaker trips to prevent damage—or even a fire. In software, the equivalent would be your service crashing because it’s overloaded with slow or failing requests from a downstream service. Without a circuit breaker, a single failure could spiral into a full outage.&lt;/p&gt;

&lt;p&gt;When a circuit breaker trips:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It goes into the &lt;strong&gt;Open&lt;/strong&gt; state, rejecting all requests to the downstream service. The error is returned immediately.&lt;/li&gt;
&lt;li&gt;After a timeout, it moves into the &lt;strong&gt;Half-Open&lt;/strong&gt; state, allowing a limited number of requests to test if the downstream service has recovered.&lt;/li&gt;
&lt;li&gt;If those requests succeed, it transitions back to &lt;strong&gt;Closed&lt;/strong&gt; , and all traffic is allowed again. If they fail, it trips back to Open.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why Use a Circuit Breaker?
&lt;/h2&gt;

&lt;p&gt;Now that we know what a circuit breaker is, why use it? What happens if we don’t?&lt;/p&gt;

&lt;p&gt;Anytime your service calls another service, it uses resources—CPU, memory, threads, connections. If the downstream service is down or very slow, your service will waste resources waiting. In high-traffic environments, this can lead to &lt;strong&gt;resource exhaustion&lt;/strong&gt; and eventually cause your own service to go down.&lt;/p&gt;

&lt;p&gt;Imagine a travel commerce site where one airline's API is down. Users should still be able to see and purchase flights from other airlines. But if your system keeps making slow calls to the failing airline API, it could eat up all your resources and take down the whole service. This leads to &lt;strong&gt;cascading failures&lt;/strong&gt; across systems.&lt;/p&gt;

&lt;p&gt;Even if your service doesn’t crash, using a circuit breaker can help with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not overloading the downstream service&lt;/strong&gt; during incidents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failing fast&lt;/strong&gt; , which improves user experience and prevents unnecessary load on your own service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s say your service has a circuit breaker and the client calling your service doesn’t. By returning a fast error instead of making a slow failing call, you help prevent cascading failures further upstream. Bonus: your users won’t have to wait several seconds for a timeout—they’ll get an immediate error, which is often a better experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Circuit Breakers Work
&lt;/h2&gt;

&lt;p&gt;Now that we’ve seen the value of a circuit breaker, let’s look at how it works in more detail.&lt;/p&gt;

&lt;p&gt;Circuit breakers typically have &lt;strong&gt;three states&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Closed&lt;/strong&gt; – Everything is working. All requests pass through to the downstream dependency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open&lt;/strong&gt; – The breaker has tripped. No requests are allowed through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Half-Open&lt;/strong&gt; – A trial state after some timeout. Some requests are allowed to test whether the downstream is back.
Let's use this chart to better visualize the state flow of the circuit breaker:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can refer to this diagram for better understanding on how the state changes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3w9iwga9y3fusskvx8od.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3w9iwga9y3fusskvx8od.png" alt="A Developer’s Guide to Circuit Breakers: Protect Your Service from Failure" width="800" height="539"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Circuit Breaker State Change Diagram&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Configuration Options
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Failure Rate Threshold&lt;/strong&gt; : Determines when the breaker should trip. You might configure it to trip if more than 50% of the last 100 requests fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reset Timeout&lt;/strong&gt; : How long the breaker should stay open before trying to move to half-open. Set it too low and you risk overloading the service again. Set it too high and recovery might be delayed unnecessarily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Half-Open Test Requests&lt;/strong&gt; : The number of requests to allow during half-open state before deciding whether to close or re-open the breaker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These configuration options may differ slightly depending on the library you use, but they’re commonly supported. Many circuit breaker libraries also let you configure timeouts and concurrency limits. Make sure to check your library’s documentation for full capabilities.&lt;/p&gt;


&lt;h2&gt;
  
  
  Circuit Breaker in Action (with Hystrix in Go)
&lt;/h2&gt;

&lt;p&gt;Let’s walk through an example using the Hystrix library in Go. Hystrix Circuit Breaker library was developed by Netflix and is available in various languages. It also provides a built-in dashboard to visualize the circuit breaker’s state.&lt;/p&gt;

&lt;p&gt;This is a simple diagram showing what we will build in this section:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzpzo2qwmfb6th8i5ne8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzpzo2qwmfb6th8i5ne8.png" alt="A Developer’s Guide to Circuit Breakers: Protect Your Service from Failure" width="800" height="578"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Circuit Breaker Example&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll create two APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;mock API&lt;/strong&gt; that always returns an error (to simulate a faulty dependency).&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;invoke API&lt;/strong&gt; that calls the mock API with a Hystrix circuit breaker.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hystrix.ConfigureCommand("mock_api_call", hystrix.CommandConfig{  
    Timeout: 1000,  
    MaxConcurrentRequests: 100,  
    RequestVolumeThreshold: 5,  
    SleepWindow: 5000,  
    ErrorPercentThreshold: 50,
})

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

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;"mock_api_call"&lt;/code&gt; identifier allows multiple breakers with different configs in a service.&lt;/p&gt;

&lt;p&gt;Then we start the Hystrix stream handler, which will allow us to connect a dashboard to visualize circuit breaker behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Start Hystrix stream handler  
hystrixStreamHandler := hystrixgo.NewStreamHandler()  
hystrixStreamHandler.Start()  
go func() {  
    log.Println("Starting Hystrix stream handler on port 8081...")  
    if err := stdhttp.ListenAndServe(":8081", hystrixStreamHandler); err != nil {  
       log.Printf("Error starting Hystrix stream handler: %v", err)  
    }  
}()

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mock API&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// HandleMockAPI handles requests to the mock API endpointfunc (h *Handler) HandleMockAPI(w http.ResponseWriter, r *http.Request) {  
    log.Println("Mock API called")  
    http.Error(w, "Internal Server Error", http.StatusInternalServerError)  
}

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

&lt;/div&gt;



&lt;p&gt;This API always returns a 500 error to simulate failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invoke API&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// HandleInvoke handles requests to the invoke endpointfunc (h *Handler) HandleInvoke(w http.ResponseWriter, r *http.Request) {  
    output := make(chan string, 1)  
    log.Println("Calling mock API")
    errors := hystrix.Go("mock_api_call", func() error {  
       log.Println("Calling mock API")  
       result, err := h.apiClient.CallMockEndpoint()  
       if err != nil {  
          return err  
       }  
       output &amp;lt;- result  
       return nil  
    }, func(err error) error {  
       // Fallback function  
       output &amp;lt;- fmt.Sprintf("Fallback: %v", err)  
       return nil  
    })  

    select {  
    case result := &amp;lt;-output:  
       fmt.Fprintln(w, result)  
    case err := &amp;lt;-errors:  
       log.Printf("Error: %v", err)  
       http.Error(w, "Error processing request", http.StatusInternalServerError)  
    }  
}

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

&lt;/div&gt;



&lt;p&gt;What this API will do is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Handles an HTTP request&lt;/strong&gt; when someone calls the endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tries to call a mock API&lt;/strong&gt; using &lt;code&gt;h.apiClient.CallMockEndpoint()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrap Hystrix&lt;/strong&gt; on the API call. Notice that we're using the &lt;code&gt;mock_api_call&lt;/code&gt; command we've setup before&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If the API call works&lt;/strong&gt; , it sends the result to the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If the API call fails&lt;/strong&gt; , it runs a fallback function and sends a fallback message instead. Which contain the error happened so we can differentiate whether the error is from the mock API or from the tripped circuit breaker.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you hit the &lt;code&gt;invoke&lt;/code&gt; API a few times, you’ll start to see this response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fallback: hystrix: circuit open

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

&lt;/div&gt;



&lt;p&gt;This means the circuit breaker has tripped and is blocking further calls to the mock API.&lt;/p&gt;

&lt;p&gt;In the log, you will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2025/04/03 14:25:18 Invoke API called
2025/04/03 14:25:18 Calling mock API
2025/04/03 14:25:18 Mock API called
2025/04/03 14:25:18 Invoke API called
2025/04/03 14:25:18 Calling mock API
2025/04/03 14:25:18 Mock API called
2025/04/03 14:25:19 Invoke API called
2025/04/03 14:25:19 Calling mock API
2025/04/03 14:25:19 Mock API called
2025/04/03 14:25:19 Invoke API called
2025/04/03 14:25:19 Calling mock API
2025/04/03 14:25:19 Mock API called
2025/04/03 14:25:19 Invoke API called
2025/04/03 14:25:19 Calling mock API
2025/04/03 14:25:19 Mock API called
2025/04/03 14:25:20 Invoke API called

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

&lt;/div&gt;



&lt;p&gt;Notice that when the circuit is open, the actual call to the mock API is skipped entirely, proving that the breaker is doing its job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoring with Hystrix Dashboard&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You can visualize how the Hystrix is running by running Hystrix dashboard in Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -p 7979:7979 --name hystrix-dashboard steeltoeoss/hystrix-dashboard

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

&lt;/div&gt;



&lt;p&gt;Then point the dashboard to:&lt;br&gt;&lt;br&gt;
&lt;code&gt;http://host.docker.internal:8081&lt;/code&gt; (use this if your app is running outside Docker).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8tgfaeov56rd5qljepcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8tgfaeov56rd5qljepcw.png" alt="A Developer’s Guide to Circuit Breakers: Protect Your Service from Failure" width="521" height="344"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Hystrix Dashboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The red number indicates the count of errors returned by the Invoke API (or more specifically, by the code wrapped in the Hystrix function). The purple number indicates how many requests were short-circuited. In this case, I hit the Invoke API 8 times—5 of which reached the mock API and returned an internal server error (ISE), while 3 were short-circuited and returned an error without hitting the mock API.&lt;/p&gt;

&lt;p&gt;You can check the full code in: &lt;a href="https://github.com/brilianfird/hystrix-circuit-breaker-demo?ref=codecurated.com" rel="noopener noreferrer"&gt;https://github.com/brilianfird/hystrix-circuit-breaker-demo&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices When Using Circuit Breakers
&lt;/h2&gt;

&lt;p&gt;You now understand how a circuit breaker works and how to configure it. But how should you tune it in a real-world system?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check your monitoring to determine the right circuit breaker configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The best way to set the circuit breaker values is by understanding how your service interacts with its downstream dependencies. Look at metrics like the typical error rate, response time, and the volume of requests sent to the downstream service. You can get these insights from your existing monitoring tools. If you don’t have monitoring in place, you can still implement a circuit breaker and use its built-in dashboard to gather this data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allow Breathing Room in the Circuit Breaker Configuration—Especially at First&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you're implementing Hystrix (or any circuit breaker) for the first time, it's a good idea to start with a more lenient configuration. Since you might not yet have monitoring in place, you won't know how often the downstream service fails or how it behaves under load. A strict configuration could unintentionally disrupt existing processes, so give your system some breathing room while you observe and learn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't hardcode the configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It's best not to hardcode your circuit breaker settings. Instead, make them configurable via properties, a database, or an external configuration service. This way, if the settings need to be adjusted, you won’t have to redeploy your application—making it much easier to recover quickly and minimize business impact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account for App Instances in Your Configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When using per-instance circuit breaker settings, it’s important to think about how your application behaves at scale. Circuit breakers often use percentage-based thresholds, which makes them more adaptable than fixed-count mechanisms like rate limiters. Still, scaling can introduce unexpected issues.&lt;/p&gt;

&lt;p&gt;For example, if you set a high request volume threshold, it might work fine in a single-instance setup. But once the app scales horizontally, each instance may receive fewer requests—potentially not enough to reach the threshold and trip the circuit breaker, even if the overall system is under stress. Always factor in your scaling strategy when defining these thresholds to avoid silent failures or delayed responses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;In this article, we explored how the Circuit Breaker pattern helps improve system resiliency.&lt;br&gt;&lt;br&gt;
However, it's just one piece of the puzzle. Other techniques—like&lt;a href="https://www.codecurated.com/blog/designing-a-retry-mechanism-for-reliable-systems/" rel="noopener noreferrer"&gt;retry mechanisms&lt;/a&gt;, the bulkhead pattern, and timeouts—also play a key role in building robust systems.&lt;/p&gt;

&lt;p&gt;Make sure to subscribe to &lt;strong&gt;Code Curated&lt;/strong&gt; so you don’t miss out when we cover these methods in future articles!&lt;/p&gt;

</description>
      <category>architecture</category>
    </item>
    <item>
      <title>Why You Should Use Caching - Improve User Experience and Reduce Costs</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Fri, 10 May 2024 02:44:46 +0000</pubDate>
      <link>https://dev.to/brilianfird/why-you-should-use-caching-improve-user-experience-and-reduce-costs-6o7</link>
      <guid>https://dev.to/brilianfird/why-you-should-use-caching-improve-user-experience-and-reduce-costs-6o7</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kz1pidzqwniv6246v25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kz1pidzqwniv6246v25.png" alt="Why You Should Use Caching - Improve User Experience and Reduce Costs" width="800" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, we're diving into the world of caching. Caching is a secret weapon for building scalable, high-performance systems. There are many types of caching, but in this article, we'll focus on backend object caching (backend caching). Mastering it will help you to build high performance and reliable software.&lt;/p&gt;

&lt;p&gt;In this article, we'll be exploring:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What is Caching?&lt;/strong&gt; We'll explore caching and explain how it temporarily stores data for faster access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefits of Caching&lt;/strong&gt; : Discover how caching boosts speed, reduces server load, improves user experience, and can even cut costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching Pattern&lt;/strong&gt; : In this section, we'll dive into different ways to use the cache. Remember, there are pros and cons to each approach, so make sure to pick the right pattern for your needs!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching Best Practice&lt;/strong&gt; : Now you know how to store and retrieve cached data. But how do you ensure your cached data stays up-to-date? And what happens when the cache reaches its capacity?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When Not To Cache&lt;/strong&gt; : While caching offers many benefits, there are times when it's best avoided. Implementing caching in the wrong system can increase complexity and potentially even slow down performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is Caching
&lt;/h2&gt;

&lt;p&gt;Creating a high-performance and scalable application is all about removing bottlenecks and making the system more efficient. Databases often bottleneck system performance due to their storage and processing requirements. This makes them a costly component because they need to be scaled up often.&lt;/p&gt;

&lt;p&gt;Thankfully, there's a component that can help offload database resource usage while improving data retrieval speed – that component is called &lt;strong&gt;cache&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cache is a temporary storage designed for fast write and read of data. It uses low-latency memory storage and optimized data structures for quick operations. Chances are you've already used Redis or Memcached, or at least heard their names. These are two of the most popular distributed caching systems for backend services. Redis can even act as a primary database, but that's a topic for another article!&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Caching
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fouc51abyidc261a35blb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fouc51abyidc261a35blb.png" alt="Why You Should Use Caching - Improve User Experience and Reduce Costs" width="800" height="502"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Latencies every developer should know&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The main benefit of caching is its speed. Reading data from a cache is significantly faster than retrieving it from a database (like SQL or Mongo). This speed comes from caches using dictionary (or HashMap) data structures for rapid operations and storing data in high-speed memory instead of on disk.&lt;/p&gt;

&lt;p&gt;Secondly, caching reduces the load on your database. This allows applications to get the data they need from the cache instead of constantly hitting the database. This dramatically decreases hardware resource usage; instead of searching for data on disk, your system simply accesses it from fast memory.&lt;/p&gt;

&lt;p&gt;These benefits directly improve user experience and can lead to cost savings. Your application responds much faster, creating a smoother and more satisfying experience for users.&lt;/p&gt;

&lt;p&gt;Caching reduces infrastructure costs. While a distributed system like Redis requires its own resources, the overall savings are often significant. Your application accesses data more efficiently, potentially allowing you to downscale your database. However, this comes with a trade-off: if your cache system fails, ensure your database is prepared to handle the increased load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Patterns
&lt;/h2&gt;

&lt;p&gt;Now that you understand the power of caching, let's dive into the best ways to use it! In this section, we'll explore two essential categories of patterns: &lt;strong&gt;Cache Writing Patterns&lt;/strong&gt; and &lt;strong&gt;Cache Miss Patterns&lt;/strong&gt;. These patterns provide strategies to manage cache updates and handle situations when the data you need isn't yet in the cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing Patterns
&lt;/h3&gt;

&lt;p&gt;Writing patterns dictate how your application interacts with both the cache and your database. Let's look at three common strategies: &lt;strong&gt;Write-back&lt;/strong&gt; , &lt;strong&gt;Write-through&lt;/strong&gt; , and &lt;strong&gt;Write-around&lt;/strong&gt;. Each offers unique advantages and trade-offs:&lt;/p&gt;

&lt;h4&gt;
  
  
  Write Back
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudp1cgd26qg0eq79ppz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudp1cgd26qg0eq79ppz3.png" alt="Why You Should Use Caching - Improve User Experience and Reduce Costs" width="800" height="191"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Write-back Cache Pattern&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your application interacts only with the cache.&lt;/li&gt;
&lt;li&gt;The cache confirms the write instantly.&lt;/li&gt;
&lt;li&gt;A background process then copies the newly written data to the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt; Write-heavy applications where speed is critical, and some inconsistency is acceptable for the sake of performance. Examples include metrics and analytics applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster reads:&lt;/strong&gt;  Data is always in the cache for quick access, bypassing the database entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster writes:&lt;/strong&gt;  Your application doesn't wait for database writes, resulting in faster response times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less database strain:&lt;/strong&gt;  Batched writes reduce database load and can potentially extend the lifespan of your database hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Risk of data loss:&lt;/strong&gt;  If the cache fails before data is saved to the database, information can be lost. Redis mitigates this risk with persistent storage, but this adds complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased complexity:&lt;/strong&gt;  You'll need a middleware to ensure the cache and database eventually stay in sync.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potential for high cache usage:&lt;/strong&gt;  All writes go to the cache first, even if the data isn't frequently read. This can lead to high storage consumption.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Write Through
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0d1gihzwkpvq28im58r0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0d1gihzwkpvq28im58r0.png" alt="Why You Should Use Caching - Improve User Experience and Reduce Costs" width="593" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Write-through Cache policy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your application writes to both the cache and the database simultaneously.&lt;/li&gt;
&lt;li&gt;To reduce wait time, you can write to the cache asynchronously. This allows your application to signal successful writes before the cache operation is completely finished.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster reads:&lt;/strong&gt;  Like Write-Back, data is always in the cache, eliminating the need for database reads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt;  Your application only confirms a write after it's saved in the database, guaranteeing data persistence even if a crash occurs immediately afterward.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slower writes:&lt;/strong&gt;  Compared to Write-Back, this policy has some overhead because the application waits for both the database and cache to write. Asynchronous writes improve this but remember, there's always the database wait time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High cache usage:&lt;/strong&gt;  All writes go to the cache, potentially consuming storage even if the data isn't frequently accessed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Write Around
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2w2ukxgb6dtuvoxxz40n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2w2ukxgb6dtuvoxxz40n.png" alt="Why You Should Use Caching - Improve User Experience and Reduce Costs" width="678" height="878"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Write-around Cache Pattern&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With Write-Around, your application writes data directly to the database, bypassing the cache during the write process. To populate the cache, it employs a strategy called the &lt;strong&gt;cache-aside pattern&lt;/strong&gt; :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read request arrives:&lt;/strong&gt;  The application checks the cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache miss:&lt;/strong&gt;  If the data isn't found in the cache, the application fetches it from the database and then stores it in the cache for future use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reliable writes:&lt;/strong&gt;  Data is written directly to the database, ensuring consistency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient cache usage:&lt;/strong&gt;  Only frequently accessed data is cached, reducing memory consumption.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Higher read latency (in some cases):&lt;/strong&gt; If data isn't in the cache, the application must fetch it from the database, adding a roundtrip compared to policies where the cache is always pre-populated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cache Miss Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehur492qqaznrh2bbd6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehur492qqaznrh2bbd6f.png" alt="Why You Should Use Caching - Improve User Experience and Reduce Costs" width="800" height="741"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Cache Miss Pattern&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A cache miss occurs when the data your application needs isn't found in the cache. Here are two common strategies to tackle this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cache-Aside&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The application checks the cache.&lt;/li&gt;
&lt;li&gt;On a miss, it fetches data from the database and then updates the cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key point:&lt;/strong&gt;  The application is responsible for managing the cache.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using Cache-Aside pattern means your application will manage the cache. This approach is the most common to use because it's simple and don't need development in places other than the application&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read-Through&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The application makes a request, unaware of the cache.&lt;/li&gt;
&lt;li&gt;A specialized mechanism checks the cache and fetches data from the database if needed.&lt;/li&gt;
&lt;li&gt;The cache is updated transparently.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read-through pattern reduce application complexity, but it increase infrastructure complexity. It help to offload the application resource to the middleware instead.&lt;/p&gt;




&lt;p&gt;Overall, the write-around pattern with cache-aside is most commonly used because of its ease of implementation. However, I recommend to also include the write-through pattern if you have any data that will be used immediately after it's cached. This will provide a slight benefit to read performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching Best Practice
&lt;/h2&gt;

&lt;p&gt;In this section, we'll explore best practices for using a cache. Following these practices will ensure your cache maintains fresh data and manages its storage effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Invalidation
&lt;/h3&gt;

&lt;p&gt;Imagine you've stored data in the cache, and then the database is updated. This causes the data in the cache to differ from the database version. We call this type of cache data "stale." Without a cache invalidation technique, your cached data could remain stale after database updates. To keep data fresh, you can use the following techniques:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cache Invalidation on Update:&lt;/strong&gt; When you update data in the database, update the corresponding cache entry as well. Write-through and write-back patterns inherently handle this, but write-around/cache-aside requires explicit deletion of the cached data. This strategy prevents your application from retrieving stale data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time To Live (TTL):&lt;/strong&gt; TTL is a policy you can set when storing data in the cache. With TTL, data is automatically deleted after a specified time. This helps clear unused data and provides a failsafe against stale data in case of missed invalidations.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cache Replacement Policies
&lt;/h3&gt;

&lt;p&gt;If you cache a large amount of data, your cache storage could fill up. Cache systems typically use memory, which is often smaller than your primary database storage. When the cache is full, it needs to delete some data to make room. Cache replacement policies determine which data to remove:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Least Recently Used (LRU):&lt;/strong&gt; This common policy evicts data that hasn't been used (read or written) for the longest time. LRU is suitable for most real-world use cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least Frequently Used (LFU):&lt;/strong&gt; Similar to LRU, but focuses on access frequency. Newly written data might be evicted, so consider adding a warm-up period during which data cannot be deleted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Other replacement policies like FIFO (First-In, First-Out), Random Replacement, etc., exist, but are less common.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Not To Cache
&lt;/h2&gt;

&lt;p&gt;Before diving into cache implementation, it's important to know when it might &lt;em&gt;not&lt;/em&gt; be the best fit. Caching often improves speed and reduces database load, but it might not make sense if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Low traffic:&lt;/strong&gt; If your application has low traffic and the response time is still acceptable, you likely don't need caching yet. Adding a cache increases complexity, so it's best implemented when you face performance bottlenecks or anticipate a significant increase in traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your system is write-heavy:&lt;/strong&gt; Caching is most beneficial in read-heavy applications. This means data in your database is updated infrequently or read multiple times between updates. If your application has a high volume of writes, caching could potentially add overhead and slow things down.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this article, we've covered the basics of caching and how to use it effectively. Here's a recap of the key points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Confirm the Need:&lt;/strong&gt;  Ensure your system is read-heavy and requires the latency reduction caching offers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose Patterns Wisely:&lt;/strong&gt;  Select cache writing and cache miss patterns that align with how your application uses data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Freshness:&lt;/strong&gt;  Implement cache invalidation strategies to prevent serving stale data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage Replacement Policy:&lt;/strong&gt;  Choose a cache replacement policy (like LRU) to handle deletions when the cache reaches its capacity.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/jboner/2841832?ref=codecurated.com" rel="noopener noreferrer"&gt;https://gist.github.com/jboner/2841832&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bytesizedpieces.com/posts/cache-types?ref=codecurated.com" rel="noopener noreferrer"&gt;https://www.bytesizedpieces.com/posts/cache-types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.techtarget.com/searchstorage/definition/cache?ref=codecurated.com" rel="noopener noreferrer"&gt;https://www.techtarget.com/searchstorage/definition/cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=dGAgxozNWFE&amp;amp;ref=codecurated.com" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=dGAgxozNWFE&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>programming</category>
      <category>cache</category>
      <category>caching</category>
    </item>
    <item>
      <title>Designing A Retry Mechanism For Reliable Systems</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Tue, 03 Jan 2023 02:00:10 +0000</pubDate>
      <link>https://dev.to/brilianfird/designing-a-retry-mechanism-for-reliable-systems-3a19</link>
      <guid>https://dev.to/brilianfird/designing-a-retry-mechanism-for-reliable-systems-3a19</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz0c5qbb4lm4u1g509lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz0c5qbb4lm4u1g509lw.png" alt="Designing A Retry Mechanism For Reliable Systems" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A retry mechanism is a critical component of many modern software systems. It allows our system to automatically retry failed operations to recover from transient errors or network outages. By automatically retrying failed operations, retry mechanisms can help software systems recover from unexpected failures and continue functioning correctly.&lt;/p&gt;

&lt;p&gt;Today, we'll take a look at these topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What is A Retry Pattern&lt;/strong&gt; : What is a retry pattern? What is it for, and why do we need to implement it in our system?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When to Retry Your Request&lt;/strong&gt; : Only some requests should be retried. It's important to understand what kind of errors from the downstream service can be retried to avoid problems with business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry Backoff Period&lt;/strong&gt; : When we retry the request to the downstream service, how long should we wait to send the request again after it fails?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How to Retry?&lt;/strong&gt; : We'll look at ways to retry from the basic to more complex.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is A Retry Pattern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Retrying is an act of sending the same request&lt;/strong&gt; if the request to downstream service failed. By using a retry pattern, you'll be improving the downstream resiliency aspect of your system. When an error happens when calling a downstream service, our system will try to call it again instead of returning an error to the upstream service.&lt;/p&gt;

&lt;p&gt;So, why do we need to do it, exactly? Microservices architecture has been gaining popularity in recent decades. While this approach has many benefits, one of the downsides of microservices architecture is introducing network communication between services. Additional network communication leads to the possibility of errors in the network while services are communicating with each other (Read &lt;a href="https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing" rel="noopener noreferrer"&gt;Fallacies of distributed computing&lt;/a&gt;). Every call to other services has a chance of getting those errors.&lt;/p&gt;

&lt;p&gt;In addition, whether you're using monolith or microservices architecture, there is a big chance that you still need to call other services that are not within your company's internal network. Calling service within a different network means your request will go through more network layers and have more chance of failure.&lt;/p&gt;

&lt;p&gt;Other than network errors, you can also get system errors like rate-limit errors, service down, and processing timeout. The errors you get may or may not be suitable to be retried. Let's head to the next section to explore it in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Retry Your Request
&lt;/h2&gt;

&lt;p&gt;Although adding a retry mechanism in your system is generally a good idea, &lt;strong&gt;not every request to the downstream service should be retried&lt;/strong&gt;. As a simple baseline, things you should consider when you want to retry are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Is it a transient error?&lt;/strong&gt; You'll need to consider whether the type of errors you're getting is transient (temporary). For example, you can retry a connection timeout error because it's usually only temporary but not a bad request error because you need to change the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is it a system error?&lt;/strong&gt; When you're getting an error message from the downstream service, it can be categorized as either: &lt;strong&gt;system error&lt;/strong&gt; or &lt;strong&gt;application error&lt;/strong&gt;. System error is generally okay to be retried because your request hasn't been processed by the downstream service yet. On the other hand, an application error usually means that something is wrong with your request, and you should not retry it. For example, if you're getting a bad request error from the downstream service, you'll always get the same error no matter how many times you've retried.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idempotency&lt;/strong&gt;. Even when you're getting an error from the downstream service, there is still a chance it has processed your request. The downstream service could send the error after it has processed the main process, but another sub-process causes errors. Idempotent API means that even if the API gets the same request twice, it will only process the first request. We can achieve it by adding some id in the request that's unique to the request so the downstream service can determine whether it should process the request. Usually, you can differentiate this with the Request Method. GET, DELETE, and PUT are usually idempotent, and POST is not. But you need to confirm the API's idempotency to the service owner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cost of retrying&lt;/strong&gt;. When you retry your request to the downstream  service, there will be additional resource usage. The additional resource usage can be in the form of additional CPU usage, blocked Thread, additional memory usage, additional bandwidth usage, etc. You need to consider this, especially if your service expects large traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The implementation cost of the retry mechanism&lt;/strong&gt;. Many programming languages already have a library that implements a retry mechanism, but you still need to determine which request to retry. You can also create your retry mechanism or every system if you want to, but of course, this means that there will be a high implementation cost for the retry mechanism.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpaayq8om10il6x56lmwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpaayq8om10il6x56lmwj.png" alt="Designing A Retry Mechanism For Reliable Systems" width="800" height="709"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Idempotency&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;✍️&lt;/p&gt;

&lt;p&gt;Many libraries have already implemented the retry mechanism gracefully. For example, if you're using the Spring Mongo library in Java Spring Boot and the connection between your apps and MongoDB is severed, it will try to reconnect.&lt;/p&gt;

&lt;p&gt;⚠️&lt;/p&gt;

&lt;p&gt;Some libraries also implement a retry mechanism by default. It's sometimes dangerous because you can be unaware that the library will retry your request.&lt;/p&gt;

&lt;p&gt;I've also compiled some common errors and whether or not they're suitable for retrying:&lt;/p&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Retry(idempotent)&lt;/th&gt;
&lt;th&gt;Retry(not idempotent)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Connection Timeout&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read Timeout&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Circuit Breaker Tripped&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400: Bad Request&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;401: Unauthorized&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404: Not Found&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;429: Too Many Request&lt;/td&gt;
&lt;td&gt;Yes (Longer backoff)&lt;/td&gt;
&lt;td&gt;Yes (Longer backoff)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500: Internal Server Error&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;503: Service Unavailable&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;Let's describe the errors shortly one by one&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connection timeout&lt;/strong&gt; : Your app failed to connect to the downstream service. Hence the downstream service isn't aware of your request, and you can retry it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read timeout&lt;/strong&gt; : The downstream app has processed your request but not returning any response for a long time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit breaker tripped&lt;/strong&gt; : This is an error if you use a circuit breaker in your service. You can retry this kind of error because your service hasn't sent its request to the downstream service&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;400 - Bad Request&lt;/strong&gt; : This error means your request to the downstream service was flagged your request as a wrong request after validating it. You shouldn't retry this error because it will always return the same error if the request is the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;401 - Unauthorized&lt;/strong&gt; : You need to authorize before sending the request. Whether you can retry this error will depend on the authentication method and the error. But generally, you will always get the same error if your request is the same&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;429 - Too many requests&lt;/strong&gt; : Your request is rate limited by the downstream service. You can retry this error, although you should confirm with the downstream service's owner how long your request will be rate limited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;500 - Internal Server Error&lt;/strong&gt; : This means the downstream service had started processing your request but failed in the middle of it. Usually, it's okay to retry this error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;503 - Service Unavailable&lt;/strong&gt; : The downstream service is unavailable due to downtime. It is okay to retry this kind of error.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Retry Backoff Period
&lt;/h2&gt;

&lt;p&gt;When your request fails to the downstream service, your system will need to wait for some time before trying again. This period is called the retry backoff period.&lt;/p&gt;

&lt;p&gt;Generally, there are three strategies for wait time between calls: Fixed Backoff, Exponential Backoff, and Random Backoff. All three of them have their advantages and disadvantages. Which one you use should depend on your API and service use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed Backoff&lt;/strong&gt;. Fixed backoff means that every time you retry your request, the delay between requests is always the same. For example, if you do a retry twice with a backoff of 5 seconds, then if the first call fails, the second request will be sent 5 seconds after. If it fails again, the third call will be sent 5 seconds after the failure.&lt;/p&gt;

&lt;p&gt;A fixed backoff period is suitable for a request coming directly from the user and needs a quick response. If the request is important and you need it to come back ASAP, then you can set the backoff period to none or close to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhu7ve73zus3z3uw9io2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhu7ve73zus3z3uw9io2a.png" alt="Designing A Retry Mechanism For Reliable Systems" width="753" height="703"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Fixed backoff&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exponential Backoff&lt;/strong&gt;. When downstream service is having a problem, it doesn't always recover quickly. What you don't want to do when the downstream service is trying to recover is to hit it multiple times in a short interval. Exponential backoff works by adding some additional backoff time every time our service attempts to call the downstream service.&lt;/p&gt;

&lt;p&gt;For example, we can configure our retry mechanism with 5-second initial backoff and add two as the multiplier every attempt. This means when our first call to the downstream service fails, our service will wait 5 seconds before the next call. If the second call fails again, the service will wait 10 seconds instead of 5 seconds before the next call.&lt;/p&gt;

&lt;p&gt;Due to its longer interval nature, exponential backoff is unsuitable for retrying a user request. But it will be perfect for a background process like notification, sending email, or webhook system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftsry1cdi1800eghnzeht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftsry1cdi1800eghnzeht.png" alt="Designing A Retry Mechanism For Reliable Systems" width="753" height="781"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Exponential backoff&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Random backoff&lt;/strong&gt; is a backoff strategy introducing randomness in its backoff interval calculation. Suppose that your service is getting a burst of traffic. Your service then calls a downstream service for every request, and then you get errors from it because the downstream service gets overwhelmed by your request. Your service implements a retry mechanism and will retry the requests in 5 seconds. But there is a problem: when it's time to retry the requests, all of them will be retried at once, and you might get an error from the downstream service again. With the randomness introduced by the random backoff mechanism, you can avoid this.&lt;/p&gt;

&lt;p&gt;A random backoff strategy will help your service to level the request to the downstream service by introducing a random value for retry. Let's say you configure the retry mechanism with 5 seconds interval and two retries. If the first call fails, the second one could be attempted after 500ms; if it fails again, the third one could be attempted after 3.8 seconds. If many requests fail the downstream service, they won't be retried simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dnlhnny5pnenz1ynxkq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1dnlhnny5pnenz1ynxkq.png" alt="Designing A Retry Mechanism For Reliable Systems" width="753" height="703"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Random backoff&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Where to store the retry state?
&lt;/h2&gt;

&lt;p&gt;When doing a retry, you'll need to store the state of the retry somewhere. The state includes how many retries have been made, the request to be retried, and the additional metadata you want to save. Generally, there are three places you can use to store the retry state, which are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thread&lt;/strong&gt; is the most common place to store the retry state. If you're using a library with a built-in retry mechanism, it will most likely use the Thread to store the state. The simplest way to do this is to sleep the Thread. Let's see some example in Java:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int retryCount = 0;

while (retryCount &amp;lt; 3) {
    try {
        thirdPartyOutboundService.getData();
    } catch (Exception e) {
        retryCount += 1;
        Thread.sleep(3000);
    }
}

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

&lt;/div&gt;



&lt;p&gt;The code above basically sleep the Thread when getting an exception and calling the process again. While this is simple, it has the disadvantage of blocking the Thread and making other processes unable to use the Thread. This method is suitable for a fixed backoff strategy with a low interval like processes that direct response to the user and need a response as soon as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Messaging&lt;/strong&gt;. We could use a popular messaging broker like RabbitMQ (delayed queue) to save a retry state. When you're getting a request from the upstream, and you fail to process it (it can be because of downstream service or not), you can publish the message to the delayed queue to consume it later (depending on your backoff).&lt;/p&gt;

&lt;p&gt;Using messaging to save the retry state is suitable for a background process request because the upstream service can't directly get the response of the retry process. The advantage of using this approach is that it's usually easy to implement because the broker/library already supports the retry function. Messaging as a storage system of retry state also works well with distributed systems. One problem can happen is your service suddenly has a problem like downtime when waiting for the next retry. By saving the retry state in the messaging broker, your service can continue the retry after the issue has been resolved.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoxm6yalxke4exvp12n2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoxm6yalxke4exvp12n2.png" alt="Designing A Retry Mechanism For Reliable Systems" width="800" height="321"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Retry using message broker&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database&lt;/strong&gt; is the most customizable solution to store the retry state, either by using a persistent storage or an in-memory KV store like Redis. When the request to the downstream service fails, you can save the data in the Database and use a cron job to check the Database every second or minute to retry failed messages.&lt;/p&gt;

&lt;p&gt;While this is the most customizable solution, the implementation cost will be very high because you'll need to implement your retry mechanism. You can either create the mechanism in your service with the downside of sacrificing a bit of performance when a retry is happening or make an entirely new service for retry purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;This article has explored what is and what aspects to consider when implementing a retry pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You need to know what request and how to retry it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you do the retry mechanism correctly, you'll help with the user experience and reduced operation of the service you're building. But, if you do it incorrectly, you risk worsening the user experience and business error. You need to understand when the request can be retried and how to retry it so you can implement the mechanism correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is much more&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we've covered about retry pattern. This pattern increases the downstream resiliency aspect of a system, but there is more to the downstream resiliency. We can combine the retry pattern with a timeout(which we explored in this article) and circuit breaker to make our system more resilient to downstream failure. If you're interested, subscribe to the newsletter because we plan to write about that too.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://understandingdistributed.systems/" rel="noopener noreferrer"&gt;Understanding Distributed System Book&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/developer-to-architect/" rel="noopener noreferrer"&gt;Developer to Architect Courses on Udemy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dzone.com/articles/understanding-retry-pattern-with-exponential-back" rel="noopener noreferrer"&gt;DZone article&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
    </item>
    <item>
      <title>How To Better Store Password In Database</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Tue, 02 Aug 2022 13:00:43 +0000</pubDate>
      <link>https://dev.to/brilianfird/how-to-better-store-password-in-database-3c1o</link>
      <guid>https://dev.to/brilianfird/how-to-better-store-password-in-database-3c1o</guid>
      <description>&lt;h2&gt;
  
  
  How Would You Store Your User's Password?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bg1jguflmjmfa4zc7ht.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4bg1jguflmjmfa4zc7ht.jpg" alt="How To Better Store Password In Database" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How would you store a password if you were asked to create an authentication system? The easiest solution would be to store the plain text inputted by the users. For example, if the users inputs their email as &lt;code&gt;codecurated@codecurated.com&lt;/code&gt; and password as &lt;code&gt;weakpassword&lt;/code&gt;, then we can insert it into our &lt;code&gt;users&lt;/code&gt; table, right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm6gy4fa4bdz83vwe9wn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm6gy4fa4bdz83vwe9wn.png" alt="How To Better Store Password In Database" width="737" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the user tries to log in, we can query the table with &lt;code&gt;SELECT * FROM users WHERE email = {email} AND password = {password}&lt;/code&gt;. If the query returns a result, then we can authenticate the user. Task done? Well, not quite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem With Storing Plain Text Password
&lt;/h2&gt;

&lt;p&gt;Even though the solution above will work, it is not secure and prone to many attacks. The most direct attack that might not be obvious is an internal attack. In this attack, the people or employees who have access to your database (including yourself) can easily see the user's password and get their credentials.&lt;/p&gt;

&lt;p&gt;A data breach is also another thing why plain text password is terrible. Someone you don't intend to might acquire your database, and it &lt;a href="https://haveibeenpwned.com/PwnedWebsites" rel="noopener noreferrer"&gt;happens all the time&lt;/a&gt;, even to a large company. With a plain text password, the attacker can get all of your user's credentials by querying your &lt;code&gt;users&lt;/code&gt; table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Way of Storing User's Password?
&lt;/h2&gt;

&lt;p&gt;The first step that you want to take is to hash your user password with a hashing function before storing it in the database. Unlike encryption, hashing function can only go one way, and the result of hashing a specific string will always be the same. This makes hashing function a very suitable process in password storing.&lt;/p&gt;

&lt;p&gt;One of the most popular and secure hashing functions is &lt;code&gt;SHA256&lt;/code&gt;. If we try to hash &lt;code&gt;weakpassword&lt;/code&gt; with &lt;code&gt;SHA256&lt;/code&gt;, the result would be:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Hashing function only goes one way, so we can't convert the hash result back to &lt;code&gt;weakpassword&lt;/code&gt;. Also, every time &lt;code&gt;weakpassword&lt;/code&gt; is hashed using &lt;code&gt;SHA256&lt;/code&gt;, the result will always be the same.&lt;/p&gt;

&lt;p&gt;Looks good. Now the attackers wouldn't be able to know the users' passwords even if they can access your database. But, it's not good enough.&lt;/p&gt;

&lt;p&gt;A Rainbow table attack is an attack with a table of a precomputed hash of common passwords. With a rainbow table attack, the attacker will be able to get the credential of the users with weak passwords in your database. To combat this, &lt;code&gt;salt&lt;/code&gt; is usually used when hashing a password. &lt;code&gt;salt&lt;/code&gt; is a randomly generated value that you can combine with the password before hashing it. For example, if we generated &lt;code&gt;jvFJ4&lt;/code&gt; as a salt and combine it with &lt;code&gt;weakpassword&lt;/code&gt; and hash it (&lt;code&gt;sha256("jvFJ4weakpassword")&lt;/code&gt;) it will produce:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Which is a completely different result that hashed plain &lt;code&gt;weakpassword&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now with &lt;code&gt;salt&lt;/code&gt;, our table will become:&lt;/p&gt;

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

&lt;p&gt;What do we need to do when the user logs in?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user will submit their email and plain password&lt;/li&gt;
&lt;li&gt;The system needs to query the &lt;code&gt;users&lt;/code&gt; table by email, e.g., &lt;code&gt;SELECT * FROM users WHERE email='codecurated@codecurated.com'&lt;/code&gt; to get the hashed password and &lt;code&gt;salt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compute &lt;code&gt;SHA-256(salt + inputted password)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compare the result with the hashed password. If it's the same, it means the user has inputted the correct password, and the system can authenticate the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have mitigated many attacks with this design, but is it enough? Well...&lt;/p&gt;

&lt;p&gt;The approaches we created previously can mitigate a lot of attacks. But not &lt;a href="https://en.wikipedia.org/wiki/Dictionary_attack" rel="noopener noreferrer"&gt;dictionary attack&lt;/a&gt;. What if the attacker gets the salt, combines it with a common password, hash the combination, and compares it with the password in the database? Only time will separate the attacker from getting your user's password. And actually, time is one variable that we can tune.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SHA256&lt;/code&gt; is unsuitable for password hashing as it is designed to hash a complex enough input(which a password often does not) and compute it quickly. I tried to do a hashing on &lt;code&gt;weakpassword&lt;/code&gt; 10 million times with my &lt;code&gt;AMD Ryzen 5 3600&lt;/code&gt;(6 Cores, 12 Threads @3.6GHz) CPU I can finish it very fast.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h := sha256.New()  
start := time.Now()  
for i := 0; i &amp;lt; 10000000; i++ {  
   h.Write([]byte("weakpassword"))  
}  
elapsed := time.Since(start)  
log.Printf("SHA256 took %s \n", elapsed)

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

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2022/07/28 16:57:00 SHA256 took 337.2232ms 

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

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;SHA-256&lt;/code&gt;, the attacker would be able to hash and compare many passwords quickly with it. We need a slower hashing function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bcrypt
&lt;/h2&gt;

&lt;p&gt;This is where &lt;code&gt;Bcrypt&lt;/code&gt; comes in. &lt;code&gt;Bcrypt&lt;/code&gt; is a password hashing function based on &lt;a href="https://en.wikipedia.org/wiki/Blowfish_(cipher)" rel="noopener noreferrer"&gt;Blowfish&lt;/a&gt; in which you can determine its cost to run. This trait, in particular, is perfect for password hashing because it will future-proof the hashing function when a faster machine comes up.&lt;/p&gt;

&lt;p&gt;Let's see &lt;code&gt;Bcrypt&lt;/code&gt; it in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i := 10; i &amp;lt; 21; i++ {  
   start := time.Now()  
   bcrypt.GenerateFromPassword([]byte("weakpassword"), i)  
   elapsed := time.Since(start)  
   fmt.Printf("cost: %d Elapsed time: %s\n", i, elapsed)  
}

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

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cost: 10 Elapsed time: 56.233ms
cost: 11 Elapsed time: 113.1521ms
cost: 12 Elapsed time: 213.0455ms
cost: 13 Elapsed time: 447.572ms
cost: 14 Elapsed time: 877.3284ms
cost: 15 Elapsed time: 1.8126554s
cost: 16 Elapsed time: 3.375513s
cost: 17 Elapsed time: 6.5935858s
cost: 18 Elapsed time: 13.3655301s
cost: 19 Elapsed time: 27.0033831s
cost: 20 Elapsed time: 53.8954938s

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

&lt;/div&gt;



&lt;p&gt;We can see that the time went parabolic compared to the cost. Higher cost means better security but a worse user experience. Just imagine if you set the cost as 20, the user will need to wait 53 seconds when logging in. But put it too low, it will be easier for the attacker to steal your user's credential.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let's do some math. Suppose you have ten million users in your  database, and the attacker has a dictionary of 1000 most common passwords. How long would it take for the attacker to calculate the password hash with &lt;code&gt;SHA256&lt;/code&gt; compared to &lt;code&gt;Bcrypt&lt;/code&gt; with the cost of 12?  &lt;/p&gt;

&lt;p&gt;First, we will need to calculate how many hash operations the attacker needs to do, which we can get by multiplying how many users we have by the number of common passwords the attacker uses. So, &lt;code&gt;10.000.000 * 1000 = 10.000.000.000&lt;/code&gt; Now we calculate the time the attacker needs to calculate the hash ten billion times. For &lt;code&gt;SHA256&lt;/code&gt;, we did a million calculations in &lt;code&gt;337.2232ms&lt;/code&gt;. So we can calculate all of the hash: &lt;code&gt;10.000.000.000/1.000.000*337.2232ms = 3372232ms&lt;/code&gt;, which is just under 1 hour.  &lt;/p&gt;

&lt;p&gt;Next, let's try with &lt;code&gt;Bcrypt&lt;/code&gt; with cost 12: &lt;code&gt;10.000.000.000*213.0455ms = 2.130455e+12ms&lt;/code&gt;, which equals to 4053377 years. As you can see, using &lt;code&gt;Bcrypt&lt;/code&gt; for your password hashing function makes a lot of difference. If a data breach happens to your database, it will buy you a lot of time to notice it and ask your users to change their passwords.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Besides determining cost, &lt;code&gt;Bcrypt&lt;/code&gt; also uses &lt;code&gt;salt&lt;/code&gt; by default, which means the attacker won't be able to do a rainbow table attack we discussed previously. Let's see what the result is if we hash &lt;code&gt;weakpassword&lt;/code&gt; with &lt;code&gt;Bcrypt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hashedPassword,_ := bcrypt.GenerateFromPassword([]byte("weakpassword"), 10)  
fmt.Printf("hashed password: %s", hashedPassword)


hashed password: $2a$10$.krQtTcne8xlhG2rJONbKu9KZepUpwl8tyC/fFIB6lRmNufvPfge2

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

&lt;/div&gt;



&lt;p&gt;If we break the result down, we will get:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0d1mmzd6ema3ge81r1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0d1mmzd6ema3ge81r1t.png" alt="How To Better Store Password In Database" width="800" height="102"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Bcrypt breakdown&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;alg&lt;/code&gt;: The has algorithm identifier, &lt;code&gt;$2a&lt;/code&gt; means &lt;code&gt;Bcrypt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cost&lt;/code&gt;: The cost of the &lt;code&gt;Bcrypt&lt;/code&gt;, remember we set this as 10 in the code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;salt&lt;/code&gt; (22 characters): Random salt for password hashing generated by the &lt;code&gt;Bcrypt&lt;/code&gt; hashing function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hashed password&lt;/code&gt; (31 characters): The hashing function result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lastly, let's see how to validate the password hashed by &lt;code&gt;Bcrypt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hashedPassword,_ := bcrypt.GenerateFromPassword([]byte("weakpassword"), 10)  
err := bcrypt.CompareHashAndPassword(hashedPassword, []byte("weakpassword"))  

if err != nil {  
   fmt.Print(err)  
} else {  
   fmt.Printf("Password true")  
}

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

&lt;/div&gt;



&lt;p&gt;As we can see, we don't need to send the cost, alg, and salt when comparing the hash and password because every required input has been added to the &lt;code&gt;Bcrypt&lt;/code&gt; hashing result itself.&lt;/p&gt;

&lt;p&gt;Let's review, there are two essential traits of &lt;code&gt;Bcrypt&lt;/code&gt; that make it suitable for password hashing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Bcrypt&lt;/code&gt; let us determine the cost to calculate the hash result, which makes it future-proof for faster machines.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Bcrypt&lt;/code&gt; calculates its forces using salt, making a rainbow table attack impossible to do.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Next Step
&lt;/h2&gt;

&lt;p&gt;We've discussed storing your user password correctly so attackers can't figure out your user's password quickly. But securely storing our users' passwords doesn't mean the attacker can't get the password. For example, the attacker can take a look when your user inputted their password to figure out the password. There is also a chance that the attacker can make a man-in-the-middle attack if your website doesn't use HTTPS.&lt;/p&gt;

&lt;p&gt;If you want to understand more about how to secure the authentication process, I urge you to read about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication" rel="noopener noreferrer"&gt;MFA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Passwordless Login (Login by OTP, &lt;a href="https://auth0.com/docs/authenticate/passwordless/authentication-methods/email-magic-link" rel="noopener noreferrer"&gt;Magic Link&lt;/a&gt;, and &lt;a href="https://webauthn.io/" rel="noopener noreferrer"&gt;WebAuthn&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Transport_Layer_Security" rel="noopener noreferrer"&gt;TLS Protocol&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://auth0.com/blog/hashing-in-action-understanding-bcrypt/" rel="noopener noreferrer"&gt;Auth0 - Hashing in Action - Understanding Bcrypt&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.topcoder.com/thrive/articles/bcrypt-algorithm?utm_source=thrive&amp;amp;utm_campaign=thrive-feed&amp;amp;utm_medium=rss-feed#:~:text=BCrypt%20Algorithm%20is%20used%20to,guess%20passwords%20twice%20as%20quickly" rel="noopener noreferrer"&gt;Topcoder - Bcrypt Algorithm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Bcrypt" rel="noopener noreferrer"&gt;Wikipedia - Bcrypt&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>programming</category>
      <category>cybersecurity</category>
      <category>authentication</category>
    </item>
    <item>
      <title>How to Implement JSON Web Token (JWT) in Java Spring Boot</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Sun, 12 Jun 2022 10:58:28 +0000</pubDate>
      <link>https://dev.to/brilianfird/how-to-implement-json-web-token-jwt-in-java-spring-boot-456h</link>
      <guid>https://dev.to/brilianfird/how-to-implement-json-web-token-jwt-in-java-spring-boot-456h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1570212851230-2554ff99f925%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDI4fHxsb2NrfGVufDB8fHx8MTY1NTAzMTU0OA%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1570212851230-2554ff99f925%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDI4fHxsb2NrfGVufDB8fHx8MTY1NTAzMTU0OA%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="How to Implement JSON Web Token (JWT) in Java Spring Boot" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JSON Web Token or JWT has been famous as a way to communicate securely between services. There are two form of JWT, JWS and JWE. The difference between them is that JWS' payload is not encrypted while JWE is.&lt;/p&gt;

&lt;p&gt;This article will explore the implementation of the JWT in Java Spring Boot. If you want to learn more about the JWT itself, you can visit my other article &lt;a href="https://codecurated.com/blog/introduction-to-jwt-jws-jwe-jwa-jwk/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The code in this article is hosted on the following GitHub repository: &lt;a href="https://github.com/brilianfird/jwt-demo" rel="noopener noreferrer"&gt;https://github.com/brilianfird/jwt-demo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Library
&lt;/h2&gt;

&lt;p&gt;For this article, we will use the &lt;code&gt;jose4j&lt;/code&gt; library. &lt;code&gt;jose4j&lt;/code&gt; is one of the popular JWT libraries in Java and has a full feature. If you want to check out other libraries (whether it's for Java or not), &lt;a href="https://jwt.io/libraries" rel="noopener noreferrer"&gt;jwt.io&lt;/a&gt; has compiled a list of them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;  
    &amp;lt;groupId&amp;gt;org.bitbucket.b_c&amp;lt;/groupId&amp;gt;  
    &amp;lt;artifactId&amp;gt;jose4j&amp;lt;/artifactId&amp;gt;  
    &amp;lt;version&amp;gt;0.7.12&amp;lt;/version&amp;gt;  
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing JWS in Java
&lt;/h2&gt;

&lt;p&gt;JSON Web Signature (JWS) consists of three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JOSE Header&lt;/li&gt;
&lt;li&gt;Payload&lt;/li&gt;
&lt;li&gt;Signature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see an example of the JOSE header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    alg:"HS264"
}

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

&lt;/div&gt;



&lt;p&gt;JOSE header store the metadata about how to handle the JWS.&lt;br&gt;&lt;br&gt;
&lt;code&gt;alg&lt;/code&gt; stores information about which signing algorithm the JWT uses.&lt;/p&gt;

&lt;p&gt;Next, let's check the payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "sub": "1234567890",
  "name": "Brilian Firdaus",
  "iat": 1651422365
}

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

&lt;/div&gt;



&lt;p&gt;JSON payload stores the data that we want to transmit to the client. It also stores some JWT claims for information purposes that we can verify.&lt;/p&gt;

&lt;p&gt;In the example above, we have three fields registered as JWT claims.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sub&lt;/code&gt; indicates the user's unique id&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; indicates the name of the user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;iat&lt;/code&gt; indicates when we created the JWT in an epoch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last part is the signature, which is the one that makes JWS secure. Usually, the signature of the JWS will be in the form of bytes. Let's see an example of a Base64 Encoded signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI

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

&lt;/div&gt;



&lt;p&gt;Now, if we see the three parts above, you might wonder how to transfer those three parts seamlessly to the consumer. The answer is with compact serialization. Using compact serialization, we can easily share the JWS with the consumer because the JWS will become one long string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Base64.encode(JOSE Header) + "." + Base64.encode(Payload) + "." + Base64.encode(signature)

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

&lt;/div&gt;



&lt;p&gt;The result will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsImtpZCI6IjIwMjItMDUtMDEifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJyaWxpYW4gRmlyZGF1cyIsImlhdCI6MTY1MTQyMjM2NX0.qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI

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

&lt;/div&gt;



&lt;p&gt;The compact serialization part is also mandatory in the JWT specification. So for a JWS to be considered a JWT, we must do a compact serialization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unprotected
&lt;/h3&gt;

&lt;p&gt;The first type of JWS we will explore is an unprotected JWS. People rarely use his type of JWS (Basically just a regular JSON), but let's explore this first to understand the base of the implementation.&lt;/p&gt;

&lt;p&gt;Let's start by creating the header. Unlike the previous example where we used the &lt;code&gt;HS256&lt;/code&gt; algorithm, now we will use no algorithm.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Producing Unprotected JWS&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test  
public void JWS_noAlg() throws Exception {  

  JwtClaims jwtClaims = new JwtClaims();  
  jwtClaims.setSubject("7560755e-f45d-4ebb-a098-b8971c02ebef"); // set sub
  jwtClaims.setIssuedAtToNow(); // set iat
  jwtClaims.setExpirationTimeMinutesInTheFuture(10080); // set exp
  jwtClaims.setIssuer("https://codecurated.com"); // set iss
  jwtClaims.setStringClaim("name", "Brilian Firdaus"); // set name
  jwtClaims.setStringClaim("email", "brilianfird@gmail.com");//set email  
  jwtClaims.setClaim("email_verified", true); //set email_verified

  JsonWebSignature jws = new JsonWebSignature();  
  jws.setAlgorithmConstraints(AlgorithmConstraints.NO_CONSTRAINTS);  
  jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.NONE);  
  jws.setPayload(jwtClaims.toJson());  

  String jwt = jws.getCompactSerialization(); //produce eyJ.. JWT
  System.out.println("JWT: " + jwt);  
}

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

&lt;/div&gt;



&lt;p&gt;Let's see what we did in the code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We set a bunch of claims (&lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;iat&lt;/code&gt;, &lt;code&gt;exp&lt;/code&gt;, &lt;code&gt;iss&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;email_verified&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;We set the signing algorithm to &lt;code&gt;NONE&lt;/code&gt; and the algorithm constraint to &lt;code&gt;NO_CONSTRAINT&lt;/code&gt; because &lt;code&gt;jose4j&lt;/code&gt; will throw an exception because the algorithm lack security&lt;/li&gt;
&lt;li&gt;We packaged JWS in the compact serialization, which will produce one string containing the JWS. The result is a JWT complied String.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see what output we get by calling the &lt;code&gt;jws.getCompactSerialization()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJub25lIn0.eyJzdWIiOiI3NTYwNzU1ZS1mNDVkLTRlYmItYTA5OC1iODk3MWMwMmViZWYiLCJpYXQiOjE2NTI1NTYyNjYsImV4cCI6MTY1MzE2MTA2NiwiaXNzIjoiaHR0cHM6Ly9jb2RlY3VyYXRlZC5jb20iLCJuYW1lIjoiQnJpbGlhbiBGaXJkYXVzIiwiZW1haWwiOiJicmlsaWFuZmlyZEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0.

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

&lt;/div&gt;



&lt;p&gt;If we try to decode it, we'll get the JWS with fields that we set before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "header": {
    "alg": "none"
  },
  "payload": {
    "sub": "7560755e-f45d-4ebb-a098-b8971c02ebef",
    "iat": 1652556266,
    "exp": 1653161066,
    "iss": "https://codecurated.com",
    "name": "Brilian Firdaus",
    "email": "brilianfird@gmail.com",
    "email_verified": true
  }
}

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

&lt;/div&gt;



&lt;p&gt;We've successfully created a JWT with Java's &lt;code&gt;jose4j&lt;/code&gt; library! Now, let's proceed to the JWT-consuming process.&lt;/p&gt;

&lt;p&gt;To consume the JWT, we can use the &lt;code&gt;JwtConsumer&lt;/code&gt; class in the &lt;code&gt;jose4j&lt;/code&gt; library. Let's see an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test  
public void JWS_consume() throws Exception {  
  String jwt = "eyJhbGciOiJub25lIn0.eyJzdWIiOiI3NTYwNzU1ZS1mNDVkLTRlYmItYTA5OC1iODk3MWMwMmViZWYiLCJpYXQiOjE2NTI1NTYyNjYsImV4cCI6MTY1MzE2MTA2NiwiaXNzIjoiaHR0cHM6Ly9jb2RlY3VyYXRlZC5jb20iLCJuYW1lIjoiQnJpbGlhbiBGaXJkYXVzIiwiZW1haWwiOiJicmlsaWFuZmlyZEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZX0.";  

  JwtConsumer jwtConsumer = new JwtConsumerBuilder()  
          // required for NONE alg  
          .setJwsAlgorithmConstraints(AlgorithmConstraints.NO_CONSTRAINTS) 
          // disable signature requirement  
          .setDisableRequireSignature()
          // require the JWT to have iat field  
          .setRequireIssuedAt() 
          // require the JWT to have exp field 
          .setRequireExpirationTime()  
          // expect the iss to be https://codecurated.com  
          .setExpectedIssuer("https://codecurated.com") 
          .build();  

  // process JWT to jwt context  
  JwtContext jwtContext = jwtConsumer.process(jwt); 
  // get JWS object
  JsonWebSignature jws = (JsonWebSignature)jwtContext.getJoseObjects().get(0);
  // get claims  
  JwtClaims jwtClaims = jwtContext.getJwtClaims(); 

  // print claims as map  
  System.out.println(jwtClaims.getClaimsMap()); 
}

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

&lt;/div&gt;



&lt;p&gt;By using &lt;code&gt;JwtConsumer&lt;/code&gt;, we can easily make rules about what to validate when processing incoming JWT. It also provides an easy way to get the JWS Object and the claims by using &lt;code&gt;.getJoseObjects()&lt;/code&gt; and &lt;code&gt;getJwtClaims()&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;Now that we know how to produce and consume JWT without a signing algorithm, it will be much easier to understand the one with it. The difference is that we need to set the algorithm and create a key(s) to generate/validate the JWT.&lt;/p&gt;

&lt;h3&gt;
  
  
  HMAC SHA-256
&lt;/h3&gt;

&lt;p&gt;HMAC SHA-256(&lt;code&gt;HS256&lt;/code&gt;) is a MAC function with a symmetric key. We will need to generate at least 32 bytes for its secret key and feed it to the &lt;code&gt;HmacKey&lt;/code&gt; class in the &lt;code&gt;jose4j&lt;/code&gt; library to ensure security.&lt;/p&gt;

&lt;p&gt;We'll use the &lt;code&gt;SecureRandom&lt;/code&gt; library in Java to ensure the key randomity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;byte[] key = new byte[32];  

SecureRandom secureRandom = new SecureRandom();  
secureRandom.nextBytes(key);

HmacKey hmacKey = new HmacKey(key);

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

&lt;/div&gt;



&lt;p&gt;The secret key should be considered as a credential, hence it should be stored in a secure environment. For recommendation, you can store it as a environment variable or in &lt;a href="https://www.vaultproject.io/" rel="noopener noreferrer"&gt;Vault&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's see how to create and consume the JWT signed with &lt;code&gt;HS256&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test  
public void JWS_HS256() throws Exception {  

  // generate key  
  byte[] key = new byte[32];  
  SecureRandom secureRandom = new SecureRandom();  
  secureRandom.nextBytes(key);  
  HmacKey hmacKey = new HmacKey(key);  

  JwtClaims jwtClaims = new JwtClaims();  
  jwtClaims.setSubject("7560755e-f45d-4ebb-a098-b8971c02ebef"); // set sub  
  jwtClaims.setIssuedAtToNow(); // set iat  
  jwtClaims.setExpirationTimeMinutesInTheFuture(10080); // set exp  
  jwtClaims.setIssuer("https://codecurated.com"); // set iss  
  jwtClaims.setStringClaim("name", "Brilian Firdaus"); // set name  
  jwtClaims.setStringClaim("email", "brilianfird@gmail.com");//set email  
  jwtClaims.setClaim("email_verified", true); //set email_verified  

  JsonWebSignature jws = new JsonWebSignature();  
  // Set alg header as HMAC_SHA256  
  jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);  
  // Set key to hmacKey  
  jws.setKey(hmacKey);  
  jws.setPayload(jwtClaims.toJson());  

  String jwt = jws.getCompactSerialization(); //produce eyJ.. JWT  

  // we don't need NO_CONSTRAINT and disable require signature anymore 
  JwtConsumer jwtConsumer = new JwtConsumerBuilder()  
          .setRequireIssuedAt()  
          .setRequireExpirationTime()  
          .setExpectedIssuer("https://codecurated.com")  
          // set the verification key  
          .setVerificationKey(hmacKey)  
          .build();  

  // process JWT to jwt context  
  JwtContext jwtContext = jwtConsumer.process(jwt);  
  // get JWS object  
  JsonWebSignature consumedJWS = (JsonWebSignature)jwtContext.getJoseObjects().get(0);  
  // get claims  
  JwtClaims consumedJWTClaims = jwtContext.getJwtClaims();  

  // print claims as map  
  System.out.println(consumedJWTClaims.getClaimsMap());  

  // Assert header, key, and claims  
  Assertions.assertEquals(jws.getAlgorithmHeaderValue(), consumedJWS.getAlgorithmHeaderValue());  
  Assertions.assertEquals(jws.getKey(), consumedJWS.getKey());  
  Assertions.assertEquals(jwtClaims.toJson(), consumedJWTClaims.toJson());  
}

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

&lt;/div&gt;



&lt;p&gt;There isn't much difference in the code compared to creating a JWS without a signing algorithm. We first made the key using &lt;code&gt;SecureRandom&lt;/code&gt; and &lt;code&gt;HmacKey&lt;/code&gt; classes. Since &lt;code&gt;HS256&lt;/code&gt; uses a symmetric key, we only need one key that we will use to sign and verify the JWT.&lt;/p&gt;

&lt;p&gt;We also set the algorithm header value to &lt;code&gt;HS256&lt;/code&gt; by using &lt;code&gt;jws.setAlgorithmheaderValue(AlgorithmIdentifiers.HMAC_SHA256&lt;/code&gt; and the key with &lt;code&gt;jws.setKey(hmacKey)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the JWT consumer, we only need to set the HMAC key by using &lt;code&gt;.setVerificationKey(hmacKey)&lt;/code&gt; on the &lt;code&gt;jwtConsumer&lt;/code&gt; object &lt;code&gt;jose4j&lt;/code&gt; will automatically determine which algorithm is used in the JWS  by parsing its JOSE header.&lt;/p&gt;

&lt;h3&gt;
  
  
  ES256
&lt;/h3&gt;

&lt;p&gt;Unlike the &lt;code&gt;HS256&lt;/code&gt; that only needs one key, we need to generate two keys for the &lt;code&gt;ES256&lt;/code&gt; algorithm, private and public keys.&lt;/p&gt;

&lt;p&gt;We can use the private key to create and verify the JWT, while we can only use public keys to verify the JWT. Due to those traits, a private key is usually stored as a credential, while a public key can be hosted in public as JWK so the consumer of the JWT can query the host and get the key by themself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jose4j&lt;/code&gt; library provides a simple API to generate private and public keys as a JWK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EllipticCurveJsonWebKey ellipticCurveJsonWebKey = EcJwkGenerator.generateJwk(EllipticCurves.P256);

// get private key
ellipticCurveJsonWebKey.getPrivateKey();

// get public key
ellipticCurveJsonWebKey.getECPublicKey();

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

&lt;/div&gt;



&lt;p&gt;Now that we know how to generate the key creating the JWT with the &lt;code&gt;ES256&lt;/code&gt; algorithm is almost the same as creating a JWT with the &lt;code&gt;HS256&lt;/code&gt; algorithm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
JsonWebSignature jws = new JsonWebSignature();  
// Set alg header as ECDSA_USING_P256_CURVE_AND_SHA256  
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256);  
// Set key to the generated private key  
jws.setKey(ellipticCurveJsonWebKey.getPrivateKey());  
jws.setPayload(jwtClaims.toJson());
...
JwtConsumer jwtConsumer = new JwtConsumerBuilder()  
        .setRequireIssuedAt()  
        .setRequireExpirationTime()  
        .setExpectedIssuer("https://codecurated.com")  
        // set the verification key as the public key  
        .setVerificationKey(ellipticCurveJsonWebKey.getECPublicKey())  
        .build();
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only different things are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We set the algorithm header as &lt;code&gt;ECDSA_USING_P256_CURVE_AND_SHA256&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We use the private key when creating the JWT&lt;/li&gt;
&lt;li&gt;We use the public key for verifying the JWT&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Hosting JWK
&lt;/h3&gt;

&lt;p&gt;We can easily create JSON Web Key Set using the &lt;code&gt;JsonWebKeySet&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@GetMapping("/jwk")  
public String jwk() throws JoseException {  
// Create public key and private key pair
  EllipticCurveJsonWebKey ellipticCurveJsonWebKey = EcJwkGenerator.generateJwk(EllipticCurves.P256);  

  // Create JsonWebkeySet object
  JsonWebKeySet jsonWebKeySet = new JsonWebKeySet();  

  // Add the public key to the JsonWebKeySet object
  jsonWebKeySet.addJsonWebKey(ellipticCurveJsonWebKey);  

  // toJson() method by default won't host the private key
  return jsonWebKeySet.toJson();  
}

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

&lt;/div&gt;



&lt;p&gt;We also need to change some properties of the key resolver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Define verification key resolver
HttpsJwks httpsJkws = new HttpsJwks("http://localhost:8080/jwk");  
HttpsJwksVerificationKeyResolver verificationKeyResolver =  
    new HttpsJwksVerificationKeyResolver(httpsJkws);  

JwtConsumer jwtConsumer = new JwtConsumerBuilder()  
    .setRequireIssuedAt()  
    .setRequireExpirationTime()  
    .setExpectedIssuer("https://codecurated.com")  
    // set verification key resolver
    .setVerificationKeyResolver(verificationKeyResolver)  
    .build();

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

&lt;/div&gt;



&lt;p&gt;Since we hosted the JSON Web Key Set, we need to query the host. &lt;code&gt;jose4j&lt;/code&gt; is also providing a simple way to do this by using &lt;code&gt;HttpsJwksVerificationKeyResolver&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing JWE in Java
&lt;/h2&gt;

&lt;p&gt;JSON Web Encryption, unlike JWS, is a type of JWT that is encrypted so that no one can see its content except the one with the private key. First, let's see an example of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJFQ0RILUVTK0EyNTZLVyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJlcGsiOnsia3R5IjoiRUMiLCJ4IjoiMEdxMEFuWUk1RVFxOUVZYjB4dmxjTGxKanV6ckxhSjhUYUdHYzk5MU9sayIsInkiOiJya1Q2cjlqUWhjRU1xaGtubHJ6S0hVemFKMlhWakFpWGpIWGZYZU9aY0hRIiwiY3J2IjoiUC0yNTYifX0.DUrC7Y_ejpt1n9c8wXetwU65sxkEYxG6RBsCUdokVODJBtwypL9VjQ.ydZx-UDWDN7jbGeESXvPHg.6ksHUeeGgGj0txFNXmsSQUCnAv52tJuGR5vgrX54vnLkryPFv2ATdLwYXZz3mAjeDes4s9otz4-Fzg1IBZ4qsfCVa6_3CVdkb8BTU4OvQx23SFEgtj8zh-8ZrqZbpKIT.p-E09mQIleNCCmwX3YL-uQ

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

&lt;/div&gt;



&lt;p&gt;The structure of the JWE is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BASE64URL(UTF8(JWE Protected Header)) || ’.’ ||
BASE64URL(JWE Encrypted Key) || ’.’ ||
BASE64URL(JWE Initialization Vector) || ’.’ ||
BASE64URL(JWE Ciphertext) || ’.’ ||
BASE64URL(JWE Authentication Tag)

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

&lt;/div&gt;



&lt;p&gt;And if we decrypt the JWE, we will get the following claims:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "iss":"https://codecurated.com",
    "exp":1654274573,
    "iat":1654256573,
    "sub":"12345"
}

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

&lt;/div&gt;



&lt;p&gt;Now, let's see how we create the JWE:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test  
public void JWE_ECDHES256() throws Exception {  
  // Determine signature algorithm and encryption algorithm  
  String alg = KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW;  
  String encryptionAlgorithm = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256;  

  // Generate EC JWK  
  EllipticCurveJsonWebKey ecJWK = EcJwkGenerator.generateJwk(EllipticCurves.P256);  

  // Create  
  JwtClaims jwtClaims = new JwtClaims();  
  jwtClaims.setIssuer("https://codecurated.com");  
  jwtClaims.setExpirationTimeMinutesInTheFuture(300);  
  jwtClaims.setIssuedAtToNow();  
  jwtClaims.setSubject("12345");  

  // Create JWE  
  JsonWebEncryption jwe = new JsonWebEncryption();  
  jwe.setPlaintext(jwtClaims.toJson());  

  // Set JWE's signature algorithm and encryption algorithm  
  jwe.setAlgorithmHeaderValue(alg);  
  jwe.setEncryptionMethodHeaderParameter(encryptionAlgorithm);  

  // Unlike JWS, to create the JWE we use the public key  
  jwe.setKey(ecJWK.getPublicKey());  
  String compactSerialization = jwe.getCompactSerialization();  
  System.out.println(compactSerialization);  

  // Create JWT Consumer  
  JwtConsumer jwtConsumer =  
      new JwtConsumerBuilder()  
          // We set the private key as decryption key  
          .setDecryptionKey(ecJWK.getPrivateKey())  
          // JWE doesn't have signature, so we disable it  
          .setDisableRequireSignature()  
          .build();  

  // Get the JwtContext of the JWE  
  JwtContext jwtContext = jwtConsumer.process(compactSerialization);  

  System.out.println(jwtContext.getJwtClaims());  
}

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

&lt;/div&gt;



&lt;p&gt;The main difference between creating and consuming JWE compared to JWS are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use a public key as the encryption key and a private key as the decryption key&lt;/li&gt;
&lt;li&gt;We don't have a signature in JWE, so the consumer will need to skip the signature requirement&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In this article, we've learned to create both JWS and JWE in Java using &lt;code&gt;jose4j&lt;/code&gt;. Hopefully, this article is useful to you. If you want to learn more about the concept of JWT, you can visit &lt;a href="https://codecurated.com/blog/introduction-to-jwt-jws-jwe-jwa-jwk/" rel="noopener noreferrer"&gt;my other article.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Introduction to JWT (Also JWS, JWE, JWA, JWK)</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Mon, 02 May 2022 06:02:02 +0000</pubDate>
      <link>https://dev.to/brilianfird/introduction-to-jwt-also-jws-jwe-jwa-jwk-jel</link>
      <guid>https://dev.to/brilianfird/introduction-to-jwt-also-jws-jwe-jwa-jwk-jel</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1484043937869-a468066a4fbd%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDYwfHxsb2NrfGVufDB8fHx8MTY1MTQ3MDY2OA%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1484043937869-a468066a4fbd%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDYwfHxsb2NrfGVufDB8fHx8MTY1MTQ3MDY2OA%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Introduction to JWT (Also JWS, JWE, JWA, JWK)" width="2000" height="1334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The security and privacy of users' data have been a growing concern for the past few years. At the same time, JWT, as one technology to combat it, has been used more and more. Understanding JWT will give you an edge over the other software engineers. JWT might seem simple at first, but it is pretty hard to understand.&lt;/p&gt;

&lt;p&gt;In this article, we will explore mainly JWT and JWS. In addition, we'll also go through JWE, JWA, and JWK quickly. This article aims to make the reader understand the concept of JWT without diving too deep into the topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are They?
&lt;/h2&gt;

&lt;p&gt;Well, let's take a look at what are the JWT, JWS, JWE, JWA, and JWK&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Web Token (JWT)
&lt;/h3&gt;

&lt;p&gt;First, let's see the definition of JWT defined in the &lt;a href="https://datatracker.ietf.org/doc/html/rfc7519" rel="noopener noreferrer"&gt;RFC 7519&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JSON Web Token (JWT) is a compact claims representation format intended for space constrained environments such as HTTP Authorization headers and URI query parameters. JWTs encode claims to be transmitted as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. JWTs are always represented using the JWS Compact Serialization or the JWE Compact Serialization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the text, we can understand that JWT is not a structure but a set of claims in the shape of either JWS or JWE as its way of securing itself. In the most basic form, the difference between JWS and JWE is that everyone can see the payload of JWS while the JWE one is encrypted.&lt;/p&gt;

&lt;p&gt;In this article, we will explore more about JWS than JWE.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Web Algorithm (JWA)
&lt;/h3&gt;

&lt;p&gt;JWA (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7518" rel="noopener noreferrer"&gt;RFC 7518&lt;/a&gt;), which stands for JSON Web Algorithm, is a specification defining which hashing and encryption algorithm to make a JWT.&lt;/p&gt;

&lt;p&gt;For example, the following are the hashing algorithms we can use to create a JWT with a JWS structure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ibiv0kz7i9lm1d9amt2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ibiv0kz7i9lm1d9amt2.png" alt="Introduction to JWT (Also JWS, JWE, JWA, JWK)" width="566" height="633"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Web Key (JWK)
&lt;/h3&gt;

&lt;p&gt;JWK (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7517" rel="noopener noreferrer"&gt;RFC 7517&lt;/a&gt;) stands for JSON Web Key. JWK is a JSON data structure that contains information about hashing function's cryptographic key. It's a way to store your hashing key in JSON format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "kty":"EC",
    "crv":"P-256",
    "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
    "y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
    "kid":"Public key used in JWS spec Appendix A.3 example"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JWK is usually used to host a public key for a hashing function with an asymmetric key (private key and public key), so the consumer can get the key by themself.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSON Web Signature (JWS)
&lt;/h3&gt;

&lt;p&gt;JWS (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7515" rel="noopener noreferrer"&gt;RFC 7515&lt;/a&gt;), which stands for JSON Web Signature, is one of the structures used by JWT. It's the most common implementation of the JWT. JWS consists of 3 parts: the JOSE header, payload, and signature.&lt;/p&gt;

&lt;p&gt;The following is an example of JWS in compact serialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;JWS compact serialization example&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If we decode the JWS, we will get JOSE (JavaScript Object Signing and Encryption) header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "alg": "HS256",
  "typ": "JWT"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next part is the signature. We won't decode it because it's a bytes value.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The most common question related to JWT (in JWS structure) is what makes it secure since everyone can decode the JWT and see its data. The JWT is secure because not everyone can create it, but only the one with the secret key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Json Web Encryption (JWE)
&lt;/h3&gt;

&lt;p&gt;JWE (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7516" rel="noopener noreferrer"&gt;RFC 7516&lt;/a&gt;), unlike JWS, encrypts its content using an encryption algorithm. The only one that can see what is inside the JWT is the one with the key.&lt;/p&gt;

&lt;p&gt;The structure of JWE compact serialization is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BASE64URL(UTF8(JWE Protected Header)) || ’.’ ||
BASE64URL(JWE Encrypted Key) || ’.’ ||
BASE64URL(JWE Initialization Vector) || ’.’ ||
BASE64URL(JWE Ciphertext) || ’.’ ||
BASE64URL(JWE Authentication Tag)

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

&lt;/div&gt;



&lt;p&gt;Let's take a look at one example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.RD09fEltrYPVNoGt2KY1Odv_5eDxkU4VX1f__P8b9zl9uzh5bmvvJy35dL-hYlUib1g63qnWBEfeSyDk5cAIQiMt6PZCBQzuWQJQlQtuo2UPLZznmLPqah37uHKB4a57q_lWf_W9soyZbO7Zj7QRNz4ZR4s5ozRHArSZcc1pAL-pYuHKyeh6Ey8t4bk66wkthjjfOjXvIfOlgbemhibegmE4GpQL6F-m0teqcAE-OxkaBRTmmb4AD5HdrCJWCIIuC52fzuWrhcoNmHM74ggtWUUjlHaKpwcVE-IWINTFaz5Pi9u4U3vnVNOZwDwB0TLSQvqnPwTZ-bYWNj8vH4TS_w.Pjo5QK1u1otxgcuBR7e8ew._OElhHugS2L6Kp04HhbFt6dLij_KXhO654RmT4JKyswYBX0wqRWt7ZzAE6eCHfJSJdMQYxqVSNloGb4OSIzYcTEo174lBZBINkHW-w2K6E0.QBDgBFizm80HLVkZvfBPCg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example uses the &lt;code&gt;RSA_OAEP_256&lt;/code&gt; key management algorithm and &lt;code&gt;AES_128_CBC_HMAC_SHA_256&lt;/code&gt; as its encryption algorithm. If we decrypted the JWE, we will get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "iss": "https://codecurated.com",
  "exp": 1651417524,
  "iat": 1651417224
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Decoding the JWT
&lt;/h2&gt;

&lt;p&gt;Now let's take a deeper look at the JWT by using the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsImtpZCI6IjIwMjItMDUtMDEifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJyaWxpYW4gRmlyZGF1cyIsImlhdCI6MTY1MTQyMjM2NX0.qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JWT in the example is a JWT with JWS compact serialization structure. We need to split the JWT by &lt;code&gt;.&lt;/code&gt; (dot), and Base64 decode them to look at what's inside it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqqt24g0i8pxitar08yz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqqt24g0i8pxitar08yz.png" alt="Introduction to JWT (Also JWS, JWE, JWA, JWK)" width="800" height="412"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Breaking down the JWT&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After splitting and decoding the JWT, we will get three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JOSE (JavaScript Object Signature and Encryption) Header&lt;/li&gt;
&lt;li&gt;Payload&lt;/li&gt;
&lt;li&gt;Signature&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  JOSE Header
&lt;/h3&gt;


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

&lt;/div&gt;


&lt;p&gt;After doing a Base64 decode on the string, we will get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "alg": "HS256",
  "kid": "2022-05-01"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part of JWT is called the JOSE header. With the JOSE header, the JWT can inform the client how to handle the JWT.&lt;/p&gt;

&lt;p&gt;Let's break down the two fields we have in our JWT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alg&lt;/code&gt;: contains the information regarding the signing algorithm of the JWT.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kid&lt;/code&gt;: contains the information of the id of the key used for verifying the JWT. We will explore more about this in the JWK section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;alg&lt;/code&gt; is the only mandatory header, and it's the only one needed for most cases, but there are many more headers you can check &lt;a href="https://datatracker.ietf.org/doc/html/rfc7515#section-4" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payload
&lt;/h3&gt;

&lt;p&gt;With the JOSE header out of the way, let's take a look at the second part, the payload.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;After we decode it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "sub": "1234567890",
  "name": "Brilian Firdaus",
  "iat": 1651422365
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part of the JWT is called the payload. There are fields with the term JWT claims ( &lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;iat&lt;/code&gt;). So, now seems like a good time to talk about JWT claims.&lt;/p&gt;

&lt;p&gt;There are three types of JWT claims:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registered Claims&lt;/li&gt;
&lt;li&gt;Public Claims&lt;/li&gt;
&lt;li&gt;Private Claims&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's break it down one by one, starting from Registered Claims. Registered claims are claims that have been documented initially in the RFC 7519.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;iss&lt;/code&gt; (Issuer): indicates who is the issuer of the JWT.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sub&lt;/code&gt; (Subject):  indicates the user's id requesting the JWT.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aud&lt;/code&gt; (Audience): shows who's the intended consumer of the JWT.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exp&lt;/code&gt; (Expiration): the expiration time of the JWT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check the complete list &lt;a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1" rel="noopener noreferrer"&gt;here&lt;/a&gt;. None of these claims are mandatory, as dictated in the RFC 7519, but they are essential in securing your JWT.&lt;/p&gt;

&lt;p&gt;The next type of claim we'll explore is private claims. These claims can be anything. It's up to the JWT creator or consumer to determine the claims name and function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: When specifying private claims, you need to be careful not to cause any collision in the name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The last one is public claims, which is a type of claim that is publicly registered through IETF. You can check the list of public claims at: &lt;a href="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" rel="noopener noreferrer"&gt;https://www.iana.org/assignments/jwt/jwt.xhtml#claims&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most people don't have any use case needing them to register their claims. For best practice, you can search the list of Public Claims and use the one suitable for your use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signature
&lt;/h3&gt;

&lt;p&gt;If you've come to this part, you might wonder what makes the JWT secure since everyone can see its content. Well, the payload of the JWS is intended for everyone to read. What makes the JWT safe is the consumer can verify who is the one issued the JWT.&lt;/p&gt;

&lt;p&gt;The signature part in JWT is created by using a hash function. If you're not familiar with a hash function, it's an algorithm that maps an object to another object. A hash function has two crucial traits which make it suitable to secure the JWT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It only works one way&lt;/li&gt;
&lt;li&gt;The results of hashing process are always the same&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we'll explore 2 of the most common hash function used in JWT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HMAC SHA-256&lt;/li&gt;
&lt;li&gt;ECDSA256&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let's break apart the signature we use in the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is generated using &lt;code&gt;HS256&lt;/code&gt; MAC algorithm with secret key (in base64) &lt;code&gt;7TgIAQCcYUA27bCI5+m7InRwp/mzQ+ArnFW/4c0Q51U=&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;HS256&lt;/code&gt; MAC algorithm receives bytes value as its secret key parameter and produces bytes value as its output. So, unlike the header and the payload, we will get bytes value if we try to decode the signature.&lt;/p&gt;

&lt;p&gt;Let's explore the digital signature or MAC algorithm more thoroughly.&lt;/p&gt;

&lt;h4&gt;
  
  
  HMAC SHA-256
&lt;/h4&gt;

&lt;p&gt;The first algorithm we'll explore is HMAC SHA-256 (&lt;code&gt;HS256&lt;/code&gt;), a MAC algorithm using a hash function with a symmetric key. Hashing function with a symmetric key means only one key for the hashing function. So, the producer and consumer of the JWT will use the same key to sign and verify the JWT. The advantage of using this algorithm is it doesn't need many CPU resources to create the hash.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The minimum bytes length recommended for the hs256 secret key is 32 bytes. The secret key must be generated with a Cryptographically-secure pseudorandom number generator to ensure its randomity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcy44epf5sdow2vvh6d7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcy44epf5sdow2vvh6d7.png" alt="Introduction to JWT (Also JWS, JWE, JWA, JWK)" width="800" height="579"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;HS256 Example&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  ECDSA-256
&lt;/h4&gt;

&lt;p&gt;ECDSA-256 (&lt;code&gt;ECDSA256&lt;/code&gt;), unlike HMAC, is an algorithm that uses hashing function with an asymmetric key. Hashing function with an asymmetric key means we will need to generate two keys. One key is called a private key, which can be used to both sign and verify the JWT signature. The other key is called a public key, which can only be used to verify the JWT signature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1dq9rge3xaxnxzqgi0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1dq9rge3xaxnxzqgi0e.png" alt="Introduction to JWT (Also JWS, JWE, JWA, JWK)" width="650" height="547"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Private and Public Key in ECDSA-256&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As their name implies, a public key can be stored in a public space (usually as a JWK), so the client that needs to verify your JWT signature can get it quickly. In contrast, a private key must be secured and treated as a credential.&lt;/p&gt;
&lt;h4&gt;
  
  
  Which Hashing Function to Choose?
&lt;/h4&gt;

&lt;p&gt;We have learned two algorithms, &lt;code&gt;HS256&lt;/code&gt; and &lt;code&gt;ECDSA256&lt;/code&gt;, but when to choose one instead of another? You can easily decide about it by thinking about whether the producer and the consumer of the JWT are not the same components.&lt;br&gt;&lt;br&gt;
If the consumer of the JWT is the same component, then you can use the &lt;code&gt;HS256&lt;/code&gt; algorithm. This hashing function's most common use case is when you're making an authentication system using JWT.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Some people consider hs256 a kind of anti-pattern because JWT is supposedly used to increase security, but most of the use case that uses this algorithm decreases security.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, suppose you plan to use JWT as an authentication session instead of a database. In that case, your system is more insecure because you can't expire the JWT, so you can't kick sessions.&lt;/p&gt;

&lt;p&gt;On the other hand, if the JWT is produced and consumed by a different component, you can use ECDSA256. This way, you can secure your key and ensure that no one else (even the public key owner) can create a JWT on your behalf.&lt;/p&gt;
&lt;h4&gt;
  
  
  Storing Public Key as JWKs (JSON Web Key Set)
&lt;/h4&gt;

&lt;p&gt;If you plan to let the public consume and verify your JWT, it's recommended to host the public key as a JWKs on a URL. This way, if the consumer wants to verify your JWT, they can query a specific URL hosting the JWKs and get the public key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "keys": [
    {
      "kty": "EC",
      "kid": "2022-05-01",
      "x": "g_pYyqY7Htj8Aa989Ura0_mwRdqJPEnhknKzaUrztj8",
      "y": "MwOFYLE-VYre92hU0iDjNx36dk7cX6xdGgdgLIPt6Ts",
      "crv": "P-256"
    },
    {
      "kty": "EC",
      "kid": "2020-01-01",
      "x": "6bw04ZlSMjxVzC7gXv75XAposOVTONh45ZPR0AeYaoU",
      "y": "vYyCSIt0m5k4Q5A_uW8h3nEYJvgA8PgREErLcaiAHgQ",
      "crv": "P-256"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might've noticed more than one key in the JSON, which is why it's called JSON Web Key &lt;strong&gt;Set&lt;/strong&gt;. If your product uses more than one key, you can host every key in the JWKs. To identify which key to use, you will need to add the &lt;code&gt;kid&lt;/code&gt; or key id field in your JOSE Header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "alg":"ES256",
    "kid":"2022-05-01"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the client will know which key to get by comparing the &lt;code&gt;kid&lt;/code&gt; in the JOSE header JWT to the one in the JWK. The other fields, combined, will make the public key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;In this article, we've learned that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JWT is an abstract concept about how to allow one or more parties to exchange information securely. The implementation of JWT comes in the form of JWS or JWE.&lt;/li&gt;
&lt;li&gt;The difference function between JWS and JWE is that JWS allows everyone to see its payload, while JWE doesn't allow it by using an encryption method.&lt;/li&gt;
&lt;li&gt;What makes JWS considered secure even though everyone can see its payload is that the creator of the JWS can be verified by its signature using MAC or Signature Verifying algorithm. This way, the consumer can be sure that the one created the JWT is the one intended.&lt;/li&gt;
&lt;li&gt;We've explored two types of algorithms, &lt;code&gt;HS256&lt;/code&gt; and &lt;code&gt;ECDSA256&lt;/code&gt;. &lt;code&gt;HS256&lt;/code&gt; is suitable when the producer and the consumer of the JWT are the same components, while &lt;code&gt;ECDSA256&lt;/code&gt; is suitable when the producer and the consumer are different components.&lt;/li&gt;
&lt;li&gt;We can use JSON Web Key Set to host a public key for hashing function with an asymmetric key. You need to set the &lt;code&gt;kid&lt;/code&gt; field in the JOSE header of your JWT so the consumer can compare it to the one in the JWKs to get a compatible key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alas, I want to thank you for reading until the end. The next step you can take is to learn how to implement it (I intend to write about it too). There are many libraries for popular programming languages that you can check &lt;a href="https://jwt.io/libraries" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Getting Started With Elasticsearch in Java Spring Boot</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Wed, 31 Mar 2021 16:54:58 +0000</pubDate>
      <link>https://dev.to/brilianfird/getting-started-with-elasticsearch-in-java-spring-boot-43p</link>
      <guid>https://dev.to/brilianfird/getting-started-with-elasticsearch-in-java-spring-boot-43p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1508739826987-b79cd8b7da12%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMXwxMTc3M3wwfDF8c2VhcmNofDc1fHxjb2RlfGVufDB8fHw%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1508739826987-b79cd8b7da12%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMXwxMTc3M3wwfDF8c2VhcmNofDc1fHxjb2RlfGVufDB8fHw%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="Getting Started With Elasticsearch in Java Spring Boot" width="2000" height="1502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both Java and Elasticsearch is a popular technology stack companies use. Java is a programming language that was released back in 1996. Currently, Java is acquired by Oracle and still in active development.&lt;/p&gt;

&lt;p&gt;Elasticsearch is a young technology when we compare it to Java, it has only released in 2010 (14 years younger than Java). It’s gaining popularity quickly and now used in many companies as a search engine.&lt;/p&gt;

&lt;p&gt;Seeing how popular they are, I’m sure that many people and companies want to connect Java with Elasticsearch to develop their own search engine. In this article, I want to teach you how to connect Java Spring Boot 2 with Elasticsearch. We will learn how to create an API that will call Elasticsearch to produce results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Java with Elasticsearch
&lt;/h2&gt;

&lt;p&gt;The first thing we must do to connect our Spring Boot project with Elasticsearch. The easiest way to do this is to use the client library provided by Elasticsearch, which we can just add to our package manager like Maven or Gradle.&lt;/p&gt;

&lt;p&gt;For this article, we’ll use a &lt;code&gt;spring-data-elasticsearch&lt;/code&gt; library provided by Spring Data, which also includes Elasticsearch’s high level client library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting our project
&lt;/h3&gt;

&lt;p&gt;Let’s start by creating our Spring Boot project with &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Spring Initialzr&lt;/a&gt;. I’ll configure my project to be like the picture below, since we’re going to use high-level client, then we can use a convenient library provided by Spring, “Spring Data Elasticsearch”:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd90aoa15y4a6u5ps5eo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxd90aoa15y4a6u5ps5eo.png" alt="Getting Started With Elasticsearch in Java Spring Boot" width="800" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding dependency to Spring Data Elasticsearch
&lt;/h3&gt;

&lt;p&gt;If you followed my Spring Initialzr configuration in the previous section, then you should already have the elasticsearch client dependency in your project. But, if you don’t, you can add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-data-elasticsearch&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating Elasticsearch client's bean
&lt;/h3&gt;

&lt;p&gt;There are 2 methods to initialize the bean, you can either use the beans defined in the spring data elasticsearch library or you can create your own bean.&lt;/p&gt;

&lt;p&gt;The first and easy one is to use the bean configured by spring data elasticsearch.&lt;/p&gt;

&lt;p&gt;For example, you can add these properties in your &lt;code&gt;application.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.elasticsearch.rest.uris&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost:9200&lt;/span&gt;
&lt;span class="py"&gt;spring.elasticsearch.rest.connection-timeout&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1s&lt;/span&gt;
&lt;span class="py"&gt;spring.elasticsearch.rest.read-timeout&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1m&lt;/span&gt;
&lt;span class="py"&gt;spring.elasticsearch.rest.password&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="py"&gt;spring.elasticsearch.rest.username&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second method is to create your own bean. You can configure the settings by creating &lt;code&gt;RestHighLevelClient&lt;/code&gt; bean. If the bean is exist, the spring data will use it as its configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ElasticsearchConfiguration&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractElasticsearchConfiguration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ElasticsearchProperties&lt;/span&gt; &lt;span class="n"&gt;elasticsearchProperties&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@Override&lt;/span&gt;
  &lt;span class="nd"&gt;@Bean&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;RestHighLevelClient&lt;/span&gt; &lt;span class="nf"&gt;elasticsearchClient&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ClientConfiguration&lt;/span&gt; &lt;span class="n"&gt;clientConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClientConfiguration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;connectedTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elasticsearchProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getHostAndPort&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withConnectTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elasticsearchProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnectTimeout&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withSocketTimeout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elasticsearchProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSocketTimeout&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;RestClients&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientConfiguration&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing the connection from our Spring Boot application to Elasticsearch
&lt;/h3&gt;

&lt;p&gt;Your Spring Boot app and Elasticsearch should be connected now that you’ve configured the bean. Since we’re going to test the connection, make sure that your Elasticsearch is up and running!&lt;/p&gt;

&lt;p&gt;To test it, we can create a bean that will create an index in the Elasticsearch in the &lt;code&gt;DemoApplication.class&lt;/code&gt;. The class would look like:&lt;br&gt;
&lt;/p&gt;

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

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DemoApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;createTestIndex&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RestHighLevelClient&lt;/span&gt; &lt;span class="n"&gt;restHighLevelClient&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;DeleteIndexRequest&lt;/span&gt; &lt;span class="n"&gt;deleteIndexRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DeleteIndexRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello-world"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;restHighLevelClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;indices&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deleteIndexRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RequestOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ignored&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;CreateIndexRequest&lt;/span&gt; &lt;span class="n"&gt;createIndexRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CreateIndexRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello-world"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;createIndexRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index.number_of_shards"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index.number_of_replicas"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;restHighLevelClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;indices&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createIndexRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RequestOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, in that code we called Elasticsearch twice with the &lt;code&gt;RestHighLevelClient,&lt;/code&gt; which we will learn later on in this article. The first call is to delete the index if it’s already exists. We used try catch that because if the index doesn’t exist then the elasticsearch will throw an error and failing our app starting process.&lt;/p&gt;

&lt;p&gt;The second call is to create an index. Since I’m only running an 1 node Elasticsearch, I configured the shards to be 1 and replicas to be 0.&lt;/p&gt;

&lt;p&gt;If everything went fine, then you should see the indices when you check your Elasticsearch. To check it, just go to &lt;a href="http://localhost:9200/_cat/indices?v" rel="noopener noreferrer"&gt;http://localhost:9200/_cat/indices?v&lt;/a&gt; and you can see the list of the indexes in your Elasticsearch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open hello-world 0NgzXS5gRxmj1eFTPMCynQ 1 1 0 0 208b 208b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats! You just connect your application to the Elasticsearch!!&lt;/p&gt;




&lt;h2&gt;
  
  
  Another ways to connect
&lt;/h2&gt;

&lt;p&gt;I recommend you to use &lt;code&gt;spring-data-elasticsearch&lt;/code&gt; library if you want to connect to Elasticsearch with Java. But, in case that you can’t use the library, there is another way to connect your apps to Elasticsearch.&lt;/p&gt;

&lt;h3&gt;
  
  
  High level client
&lt;/h3&gt;

&lt;p&gt;As we know in the previous section, the &lt;code&gt;spring-data-elasticsearch&lt;/code&gt; library we use also includes Elasticsearch’s high level client. If you’ve already imported &lt;code&gt;spring-data-elasticsearch&lt;/code&gt;, then you can already use the Elasticsearch’s high level client.&lt;/p&gt;

&lt;p&gt;If you want to, it’s also possible to use the high level client library directly without spring data’s dependency. You just need to add this dependency in your dependency manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.elasticsearch.client&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;elasticsearch-rest-high-level-client&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;8.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll also use this client in our examples because the function in high level client is more complete than the &lt;code&gt;spring-data-elasticsearch.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For more information, you can read &lt;a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-getting-started.html" rel="noopener noreferrer"&gt;Elasticsearch documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Low level client
&lt;/h3&gt;

&lt;p&gt;Elasticsearch’s low level client. You’ll have a harder time with this library, but you can customize it more. To use it, you can add the following dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.elasticsearch.client&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;elasticsearch-rest-client&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;8.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information, you can read &lt;a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-low.html" rel="noopener noreferrer"&gt;Elasticsearch documentation&lt;/a&gt; about this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transport Client
&lt;/h3&gt;

&lt;p&gt;Elasticsearch also provides transport client, which will make your application identify as one of the node of Elasticsearch. I don’t recommend this method because it will be deprecated soon.&lt;/p&gt;

&lt;p&gt;If you’re interested, you can read about transport client &lt;a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  REST call
&lt;/h3&gt;

&lt;p&gt;The last way to connect to Elasticsearch is by doing a REST call. Since Elasticsearch uses REST API to connect to its client, you basically can use a REST call to connect your apps to Elasticsearch. You can use OKHTTP, Feign or Web Client to connect your apps with Elasticsearch.&lt;/p&gt;

&lt;p&gt;I also don’t recommend this method because it’s a hassle. Since Elasticsearch already provides client libraries, it’s better to use them instead. Only use this method if you don’t have any other way to connect.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using Spring Data Elasticsearch
&lt;/h2&gt;

&lt;p&gt;First, let’s learn how to use &lt;code&gt;spring-data-elasticsearch&lt;/code&gt; in our spring project. &lt;code&gt;spring-data-elasticsearch&lt;/code&gt; is a very easy to use and high level library we can use to access the Elasticsearch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating entity and configuring our index
&lt;/h3&gt;

&lt;p&gt;After we’re done connecting your apps with Elasticsearch, it’s time to create an entity! With spring data, we can add a metadata in our entity, which will be read by the repository bean we created. This way the code will be much cleaner and faster to develop since we don’t need to create any mapping logic in our service level.&lt;/p&gt;

&lt;p&gt;Let’s create an entity called &lt;code&gt;Product&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Data&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class="nd"&gt;@NoArgsConstructor&lt;/span&gt;
&lt;span class="nd"&gt;@Builder&lt;/span&gt;
&lt;span class="nd"&gt;@Document&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"product"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shards&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refreshInterval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"5s"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FieldType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FieldType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Keyword&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FieldType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;CLOTHES&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;ELECTRONICS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="no"&gt;GAMES&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let me explain what’s going on in the code block above. First, I won’t explain about &lt;code&gt;@Data&lt;/code&gt; &lt;code&gt;@AllArgsConstructor&lt;/code&gt; &lt;code&gt;@NoArgsConstructor&lt;/code&gt; &lt;code&gt;@Builder&lt;/code&gt; . They’re annotations from Lombok library for constructor, getter, setter, builder, and other things. If you don’t know about them yet, I urge you to &lt;a href="https://projectlombok.org/" rel="noopener noreferrer"&gt;check it out&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let’s talk about the first spring data annotation in the Entity, &lt;code&gt;@Document&lt;/code&gt; . &lt;code&gt;@Document&lt;/code&gt; annotation show that the class is an entity containing a metadata of the Elasticsearch index’s setup. To use spring data repository, which we’ll learn later on, the &lt;code&gt;@Document&lt;/code&gt; annotation is mandatory.&lt;/p&gt;

&lt;p&gt;The only annotation that is mandatory in the &lt;code&gt;@Document&lt;/code&gt; is the &lt;code&gt;indexName&lt;/code&gt;. It should be pretty clear from the name, we should fill it with the Index name we want to use for the entity. In this article, we’ll use the same name as the entity, &lt;code&gt;product&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second parameter of the &lt;code&gt;@Document&lt;/code&gt; to talk about is the &lt;code&gt;createIndex&lt;/code&gt; parameter. If you set the &lt;code&gt;createIndex&lt;/code&gt; as true, your apps will create an index automatically when you’re starting the apps if the index doesn’t yet exist.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shards&lt;/code&gt;, &lt;code&gt;replicas&lt;/code&gt; and &lt;code&gt;refreshInterval&lt;/code&gt; parameters determine the index settings when the index is created. If you change the value of those parameters after the index is already created, the settings won’t be applied. So, the parameters will only be used when creating the index for the first time.&lt;/p&gt;

&lt;p&gt;If you want to use a custom id in the Elasticsearch, you can use &lt;code&gt;@Id&lt;/code&gt; annotations. If you use the &lt;code&gt;@Id&lt;/code&gt; annotations, spring data will tell Elasticsearch to store the id in the document and the document source.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@Field&lt;/code&gt; type will determine the &lt;a href="https://www.google.com/search?q=elasticsearch+mapping&amp;amp;oq=elasticsearch+mapping&amp;amp;aqs=chrome..69i57.2238j0j1&amp;amp;sourceid=chrome&amp;amp;ie=UTF-8" rel="noopener noreferrer"&gt;field mapping&lt;/a&gt; of the field. Like &lt;code&gt;shards&lt;/code&gt;, &lt;code&gt;replicas&lt;/code&gt; and &lt;code&gt;refreshInterval&lt;/code&gt;, the &lt;code&gt;@Field&lt;/code&gt; type will only affect Elasticsearch when first creating the index. If you add a new field or change types when the index is already created, it won’t do anything.&lt;/p&gt;

&lt;p&gt;Now that we configured the entity, let’s try out the automatic index creation by spring data! When we configure the &lt;code&gt;createIndex&lt;/code&gt; as true, spring data will check whether the index exists in Elasticsearch. If it doesn’t exist, spring data will create the index with the configuration we created in the entity.&lt;/p&gt;

&lt;p&gt;Let’s start our apps, after it is running, let’s check the settings and see if it’s correct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:9200/product/_settings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"routing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"allocation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"_tier_preference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"data_content"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"refresh_interval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"number_of_shards"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"provided_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"creation_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1607959499342"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"store"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fs"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"number_of_replicas"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"iuoO8lE6QyWVSoECxa0I8w"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7100099"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything is as we configured! The &lt;code&gt;refresh_interval&lt;/code&gt; is set to &lt;code&gt;5s&lt;/code&gt;, the &lt;code&gt;number_of_shards&lt;/code&gt; is 1 and &lt;code&gt;number_of_replicas&lt;/code&gt; is 0.&lt;/p&gt;

&lt;p&gt;Now let's check the mappings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:9200/product/_mappings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mappings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"keyword"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"long"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mappings are also as we expected. It’s the same as we configured in the entity class!&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic CRUD with spring data repository interface
&lt;/h3&gt;

&lt;p&gt;After we created the entity, we’ve everything we need to create a repository interface in Spring Boot. Let’s create a repository called &lt;code&gt;ProductRepository&lt;/code&gt;. When you’re creating an interface, make sure to extend &lt;code&gt;ElasticsearchRepository&amp;lt;T, U&amp;gt;&lt;/code&gt;. In this case, the &lt;code&gt;T&lt;/code&gt; object is your entity and &lt;code&gt;U&lt;/code&gt; object type you want to use for the data id. In our case, since we’ll use &lt;code&gt;Product&lt;/code&gt; entity, we created earlier than &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;String&lt;/code&gt; as &lt;code&gt;U&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ElasticsearchRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, your repository interface is done, you don’t need to take care about the implementation because spring is taking care of that. Now, you can call every function in the classes that your repository extends to.&lt;/p&gt;

&lt;p&gt;For the examples of CRUD, you can check the codes below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpringDataProductServiceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SpringDataProductService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="nf"&gt;createProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deleteProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Iterable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;insertBulk&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;productRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;products&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code blocks above, we created a service class called &lt;code&gt;SpringDataProductServiceImpl&lt;/code&gt; which is autowired to &lt;code&gt;ProductRepository&lt;/code&gt; we created before.&lt;/p&gt;

&lt;p&gt;There are 4 basic CRUD function in it. The first one is &lt;code&gt;createProduct&lt;/code&gt; which as its name will create a new product in the &lt;code&gt;product&lt;/code&gt; index. The second one, &lt;code&gt;getProduct&lt;/code&gt; is to get the product we’ve indexed by its id. The &lt;code&gt;deleteProduct&lt;/code&gt; function can be used to delete the product in the index by id. &lt;code&gt;insertBulk&lt;/code&gt; function will allow you to insert multiple products to Elasticsearch.&lt;/p&gt;

&lt;p&gt;All is done! I won’t write about the API testing in this article because I want to focus about how our apps can interact with Elasticsearch. But, if you want to try the API, I left a GitHub link in the end of the article so you can clone and try this project after you’re done with this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom query methods in the spring data
&lt;/h3&gt;

&lt;p&gt;In the previous section, we only take advantage of using the basic methods that are already defined in the other classes. But we can also create a custom query methods to use. What’s very convenient about spring data is that you can make a method in the repository interface and you don’t need to code any implementation. Spring data library will read the repository and automatically create the implementations for it.&lt;/p&gt;

&lt;p&gt;Let’s try searching for products by the &lt;code&gt;name&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ElasticsearchRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAllByName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, that’s all you need to do to create a function in spring data repository interface.&lt;/p&gt;

&lt;p&gt;You can also define a custom query with &lt;code&gt;@Query&lt;/code&gt; annotation and insert a JSON query in the parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ElasticsearchRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAllByName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@Query&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{\"match\":{\"name\":\"?0\"}}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAllByNameUsingAnnotations&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of the methods we’ve created do the same thing, use the match query with name as its parameter. If you try it, you’ll get the same results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using ElasticsearchRestTemplate
&lt;/h3&gt;

&lt;p&gt;If you want to do a more advanced query, like aggregations, highlighting or suggestions, you can use &lt;code&gt;ElasticsearchsearchRestTemplate&lt;/code&gt; provided by the spring data library. By using it, you can create your own query as complex as you want.&lt;/p&gt;

&lt;p&gt;For example, let’s create a function for doing a match query to the &lt;code&gt;name&lt;/code&gt; field like before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getProductsByName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NativeSearchQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;QueryBuilders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;matchQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;SearchHits&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;searchHits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elasticsearchRestTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;searchHits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;SearchHit:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getContent&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should notice that the code above is more complex than the one we defined in the &lt;code&gt;ElasticserchRepository&lt;/code&gt;. It is recommended to use the spring data repository if you can. But, for more advanced query like aggregation, highlighting or suggestions, you must use the &lt;code&gt;ElasticsearchRestTemplate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, let’s write a code that will aggregate a term:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;aggregateTerm&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Query&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NativeSearchQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addAggregation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TermsAggregationBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;SearchHits&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;searchHits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elasticsearchRestTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;searchHits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAggregations&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aggregation&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nc"&gt;Terms&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;aggregation&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getBuckets&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getKeyAsString&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDocCount&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="o"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Elasticsearch RestHighLevelClient
&lt;/h3&gt;

&lt;p&gt;If you’re not using spring, or your spring version doesn’t support &lt;code&gt;spring-data-elasticsearch&lt;/code&gt;, you can use a Java library developed by Elasticsearch, &lt;code&gt;RestHighLevelClient&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RestHighLevelClient&lt;/code&gt; is a library you can use to do from basic things like CRUD to managing your Elasticsearch. Even though the name is high level, it’s actually more low level if you compare it to &lt;code&gt;spring-data-elasticsearch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The advantage of this library over spring data is that you can also manage your Elasticsearch with it. It provides index and elasticsearch configuration, which you can use more flexibility compared to spring data. It’s also has a more complete function that interact with Elasticsearch. The disadvantage of this library over spring data is this library is more low level, which means you must code more.&lt;/p&gt;

&lt;h3&gt;
  
  
  CRUD with RestHighLevelClient
&lt;/h3&gt;

&lt;p&gt;Let’s see how we can create a simple create a function with the library so we can compare it to the previous methods we’ve used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="nd"&gt;@Slf4j&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighLevelClientProductServiceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;HighLevelClientProductService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RestHighLevelClient&lt;/span&gt; &lt;span class="n"&gt;restHighLevelClient&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt; &lt;span class="n"&gt;objectMapper&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="nf"&gt;createProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;IndexRequest&lt;/span&gt; &lt;span class="n"&gt;indexRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IndexRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"product"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;indexRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="n"&gt;indexRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;IndexResponse&lt;/span&gt; &lt;span class="n"&gt;indexResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;restHighLevelClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RequestOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indexResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;RestStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ACCEPTED&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wrong status: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;indexResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error indexing, product: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it’s now more complicated and harder to implement. Now, you need to handle the exception and also convert the JSON result to your entity. It’s recommended to use spring data instead for basic CRUD because &lt;code&gt;RestHighLevelClient&lt;/code&gt; is more complicated.&lt;/p&gt;

&lt;p&gt;I’ve included another CRUD functions in the GitHub project. If you’re interested, you can check it out. The link is at the end of this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Index Creation
&lt;/h3&gt;

&lt;p&gt;This section is where the &lt;code&gt;RestHighLevelClient&lt;/code&gt; holds a clear advantage compared to spring data elasticsearch. When we’re creating an index with its mappings and settings in the previous section, we’ve only used annotations. It’s very easy to do, but you can’t do much with it.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;RestHighLevelClient&lt;/code&gt;, you can create methods for index managements, or basically almost anything that Elasticsearch REST API allows.&lt;/p&gt;

&lt;p&gt;For example, let’s write a code that will creates &lt;code&gt;product&lt;/code&gt; index with the settings and mappings we used before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;createProductIndex&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;CreateIndexRequest&lt;/span&gt; &lt;span class="n"&gt;createIndexRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CreateIndexRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"product"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;createIndexRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"number_of_shards"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"number_of_replicas"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index.requests.cache.enable"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mappings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="n"&gt;mappings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singletonMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;mappings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"category"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singletonMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"keyword"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;mappings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singletonMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"long"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;createIndexRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singletonMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"properties"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mappings&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;CreateIndexResponse&lt;/span&gt; &lt;span class="n"&gt;createIndexResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;restHighLevelClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;indices&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createIndexRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RequestOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEFAULT&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;createIndexResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAcknowledged&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let’s see what we did in the code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We initialized the &lt;code&gt;createIndexRequest&lt;/code&gt; when also determining the index name.&lt;/li&gt;
&lt;li&gt;We added the settings in the request when calling &lt;a href="https://codecurated.com/blog/how-to-connect-java-with-elasticsearch/createIndexRequest.settings" rel="noopener noreferrer"&gt;&lt;code&gt;createIndexRequest.settings&lt;/code&gt;&lt;/a&gt;. In the settings, we also configured the field &lt;a href="https://codecurated.com/blog/how-to-connect-java-with-elasticsearch/index.requests.cache.enable" rel="noopener noreferrer"&gt;&lt;code&gt;index.requests.cache.enable&lt;/code&gt;&lt;/a&gt;, which is not possible with spring data library.&lt;/li&gt;
&lt;li&gt;We made a &lt;code&gt;Map&lt;/code&gt; containing the properties and mappings of the fields in the index.&lt;/li&gt;
&lt;li&gt;We called the Elasticsearch with &lt;a href="https://codecurated.com/blog/how-to-connect-java-with-elasticsearch/restHighlevelClient.indices.create" rel="noopener noreferrer"&gt;&lt;code&gt;restHighlevelClient.indices.create&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you can see, with the &lt;code&gt;RestHighLevelClient&lt;/code&gt; we can create a more customized call for creating index to Elasticsearch compared to the annotations in spring data entity. There are also many more function in the &lt;code&gt;RestHighLevelClient&lt;/code&gt; that aren’t exist in the spring data library. You can read &lt;a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html" rel="noopener noreferrer"&gt;Elasticsearch’s documentation&lt;/a&gt; for more information about the library.&lt;/p&gt;




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

&lt;p&gt;In this article, we’ve learned two ways to connect to Elasticsearch, by using spring data and Elasticsearch client. Both are powerful library, but you should use only the spring data if it’s possible for your use case. The code with spring data elasticsearch is more readable and easy to use.&lt;/p&gt;

&lt;p&gt;If you want a more powerful library that can basically do anything the Elasticsearch allows, though, then you can also use Elasticsearch high level client. You can also use the low level client, which we didn’t cover in this article, if you need even more powerful feature.&lt;/p&gt;

&lt;p&gt;I’d also like to say that this article is to help you get started with Elasticsearch in Java Spring Boot. If you want to learn more about the libraries, you can check out &lt;a href="https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#new-features" rel="noopener noreferrer"&gt;spring data elasticsearch documentation&lt;/a&gt; and &lt;a href="https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html" rel="noopener noreferrer"&gt;Elasticsearch’s high level client documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alas, thank you for reading until the end! &lt;/p&gt;

&lt;p&gt;Previously published at &lt;a href="https://codecurated.com/blog/how-to-connect-java-with-elasticsearch/" rel="noopener noreferrer"&gt;Code Curated&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>elasticsearch</category>
      <category>java</category>
      <category>tutorials</category>
    </item>
    <item>
      <title>Create a Simple Autocomplete With Elasticsearch</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Tue, 22 Dec 2020 05:17:47 +0000</pubDate>
      <link>https://dev.to/brilianfird/create-a-simple-autocomplete-with-elasticsearch-4ldh</link>
      <guid>https://dev.to/brilianfird/create-a-simple-autocomplete-with-elasticsearch-4ldh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47h6k70ynt9au8jzlgay.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47h6k70ynt9au8jzlgay.jpg" alt="Create a Simple Autocomplete With Elasticsearch" width="700" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Autocomplete is a feature to predict the rest of a word a user is typing. It is an important feature to implement that can improve the user’s experience of your product.&lt;/p&gt;

&lt;p&gt;Creating an autocomplete might sound daunting at first if you’ve never created one. But with the help of the features in &lt;a href="https://www.elastic.co/elasticsearch/" rel="noopener noreferrer"&gt;Elasticsearch&lt;/a&gt;, it’s actually a simple thing to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things You Should Know
&lt;/h2&gt;

&lt;p&gt;If you have little knowledge of Elasticsearch, I suggest that you read my other articles first. We do not require this, but knowing how an analyzer and a text field work definitely will help you understand this article.&lt;/p&gt;

&lt;p&gt;The article “&lt;a href="https://codecurated.com/blog/basics-of-elasticsearch-for-developer/" rel="noopener noreferrer"&gt;Basics of Elasticsearch for Developer&lt;/a&gt;” will introduce you to Elasticsearch. The article “&lt;a href="https://codecurated.com/blog/elasticsearch-text-vs-keyword/" rel="noopener noreferrer"&gt;Elasticsearch: Text vs. Keyword&lt;/a&gt;” will teach you the difference between text and keyword in Elasticsearch and also will explain how Elasticsearch’s analyzer works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the index
&lt;/h3&gt;

&lt;p&gt;First, let’s create an index called &lt;code&gt;autocomplete-example&lt;/code&gt;. We will use this index for the examples in this article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request PUT \
  --url http://localhost:9200/autocomplete-example/ \
  --header 'content-type: application/json'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "autocomplete-example"
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defining a mapping
&lt;/h3&gt;

&lt;p&gt;Before indexing a document, let’s first define a mapping. We will only need one field, simple_autocomplete, with field data type text and will use a standard analyzer.&lt;/p&gt;

&lt;p&gt;Since Elasticsearch uses the standard analyzer as default, we need not define it in the mapping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request PUT \
  --url http://localhost:9200/autocomplete-example/_mapping \
  --header 'content-type: application/json' \
  --data '{
 "properties": {
  "simple_autocomplete" : {
   "type":"text"
  }
 }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "acknowledged": true
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Indexing a document
&lt;/h3&gt;

&lt;p&gt;Let’s index a document. For the examples in this article, we will only need one document, containing the text “Hong Kong.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/autocomplete-example/_doc \
  --header 'content-type: application/json' \
  --data '{
 "simple_autocomplete": "Hong Kong"
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_index": "autocomplete-example",
  "_type": "_doc",
  "_id": "aFAbznQBPNT8JhPaDhND",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Querying the Index With match Query
&lt;/h3&gt;

&lt;p&gt;Let’s start with the query that we normally use, &lt;code&gt;match&lt;/code&gt; query.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;standard&lt;/code&gt; analyzer will lowercase your indexed text and split the text to tokens on stop words before storing it to an inverted index.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;match&lt;/code&gt; query by default will use the &lt;code&gt;index-time&lt;/code&gt; analyzer, so the analyzer it uses is the same as the one indexed in the index, which is &lt;code&gt;standard&lt;/code&gt; analyzer.&lt;/p&gt;

&lt;p&gt;Let’s see how our “Hong Kong” text looks in the inverted index with the API provided by the Elasticsearch:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request GET \
  --url 'http://localhost:9200/_analyze?pretty=' \
  --header 'content-type: application/json' \
  --data '{
 "analyzer": "standard",
 "text": "Hong Kong"
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "tokens": [
    {
      "token": "hong",
      "start_offset": 0,
      "end_offset": 4,
      "type": "&amp;lt;ALPHANUM&amp;gt;",
      "position": 0
    },
    {
      "token": "kong",
      "start_offset": 5,
      "end_offset": 9,
      "type": "&amp;lt;ALPHANUM&amp;gt;",
      "position": 1
    }
  ]
}

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

&lt;/div&gt;



&lt;p&gt;When we do a search query to the index with match query, we will only get a result when we type text containing either “Hong” or “Kong.” This is because Elasticsearch only returns a result when the analyzed query is an exact match with a token in the inverted index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url 'http://localhost:9200/autocomplete-example/_doc/_search?pretty=' \
  --header 'content-type: application/json' \
  --data '{
 "query": {
  "match": {
   "simple_autocomplete": "Hong"
  }
 }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.5753642,
    "hits": [
      {
        "_index": "autocomplete-example",
        "_type": "_doc",
        "_id": "aFAbznQBPNT8JhPaDhND",
        "_score": 0.5753642,
        "_source": {
          "simple_autocomplete": "Hong Kong"
        }
      }
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;If the user type “Ho” or “Kon” or “Hon Kon,” there won’t be any response from Elasticsearch.&lt;/p&gt;

&lt;p&gt;For an autocomplete, this one isn’t very useful to help the user, right? At the least, autocomplete needs to show something, even if we do not type the full words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url 'http://localhost:9200/autocomplete-example/_doc/_search?pretty=' \
  --header 'content-type: application/json' \
  --data '{
 "query": {
  "match": {
   "simple_autocomplete": "Hon"
  }
 }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 9,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": [
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;To fix it, we can use a match_phrase_prefix query provided by Elasticsearch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using match_phrase_prefix Query
&lt;/h3&gt;

&lt;p&gt;match_phrase_prefix query will allow the user to get a result without typing all the words. By using the usual match query, we won’t get any result from the Elasticsearch if we type “Hon” or “Kon,” but with match_pharse_prefix, we can get a result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url 'http://localhost:9200/autocomplete-example/_doc/_search?pretty=' \
  --header 'content-type: application/json' \
  --data '{
 "query": {
  "match_phrase_prefix": {
   "simple_autocomplete": {
    "query": "Hon"
   }
  }
 }
}'


curl --request POST \
  --url 'http://localhost:9200/autocomplete-example/_doc/_search?pretty=' \
  --header 'content-type: application/json' \
  --data '{
 "query": {
  "match_phrase_prefix": {
   "simple_autocomplete": {
    "query": "Kon"
   }
  }
 }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.2876821,
    "hits": [
      {
        "_index": "autocomplete-example",
        "_type": "_doc",
        "_id": "aFAbznQBPNT8JhPaDhND",
        "_score": 0.2876821,
        "_source": {
          "simple_autocomplete": "Hong Kong"
        }
      }
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;There is still a shortcoming of this autocomplete: If the user types “Hon Kon,” it still won’t return any result. This is because “Hon Kon” is not the prefix of “Hong Kong”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url 'http://localhost:9200/autocomplete-example/_doc/_search?pretty=' \
  --header 'content-type: application/json' \
  --data '{
 "query": {
  "match_phrase_prefix": {
   "simple_autocomplete": {
    "query": "Hon Kon"
   }
  }
 }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": [
    ]
  }
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Pros and Cons
&lt;/h2&gt;

&lt;p&gt;An autocomplete with a text field data type and the standard analyzer is very simple, but it has pros and cons that you can consider before using this type of autocomplete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easy to no setup&lt;/strong&gt; : You don’t even have to define any mapping because by default, if you index a text document into Elasticsearch, it will get mapped into the text and keyword field data types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast index time&lt;/strong&gt; : Because this type of autocomplete is using the standard analyzer, it doesn’t process your text much when saving it to the inverted index, which translates to fast index time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enough most of the time&lt;/strong&gt; : Most of the time, you don’t need a complex autocomplete. This autocomplete type will be enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can’t handle typos&lt;/strong&gt; : This type of autocomplete can’t handle typos, so if the user types one wrong word, it won’t return any result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The query can’t start from the middle word&lt;/strong&gt; : The text queried to this type of autocomplete also can’t start from the middle. In the previous example of “Hong Kong,” if we do a query with text “ong kong,” the Elasticsearch won’t return anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can’t handle space character&lt;/strong&gt; : If we had mistakenly typed “HongKong” in the previous example, the Elasticsearch wouldn’t have returned anything with this type of autocomplete.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Use
&lt;/h2&gt;

&lt;p&gt;I recommend an autocomplete with only the standard analyzer when you only need a simple autocomplete. You can also use this type of autocomplete if the index you want to create an autocomplete of is already in production and indexed with documents. Since this autocomplete uses the default analyzer and default mapping for text, it will work for most text documents.&lt;/p&gt;

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

&lt;p&gt;Creating an autocomplete with the text field data type and standard analyzer is the simplest and easiest autocomplete that we can build with Elasticsearch. It requires almost no setup and can usually create an autocomplete for an existing index.&lt;/p&gt;

&lt;p&gt;Even if it’s enough for most use cases, it still has many weaknesses because it can only handle simple queries. To overcome that, we can use a custom-defined analyzer or the Suggesters feature in Elasticsearch, which I plan to write about. Please wait for it!&lt;/p&gt;

&lt;p&gt;At last, I want to say thank you to you for reading this article until the end. I hope this article will help you with your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://opster.com/elasticsearch-glossary/elasticsearch-auto-complete-guide/" rel="noopener noreferrer"&gt;https://opster.com/elasticsearch-glossary/elasticsearch-auto-complete-guide/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase-prefix.html" rel="noopener noreferrer"&gt;https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase-prefix.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html" rel="noopener noreferrer"&gt;https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html" rel="noopener noreferrer"&gt;https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html" rel="noopener noreferrer"&gt;https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elasticsearch</category>
      <category>tutorials</category>
    </item>
    <item>
      <title>Functional Programming in Java, Explained</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Tue, 15 Dec 2020 11:13:02 +0000</pubDate>
      <link>https://dev.to/brilianfird/functional-programming-in-java-explained-1gd2</link>
      <guid>https://dev.to/brilianfird/functional-programming-in-java-explained-1gd2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4weksg9xj7qgeatc1jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4weksg9xj7qgeatc1jh.png" alt="Functional Programming in Java, Explained" width="768" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re a Java developer, I’m sure that you have seen code similar to the featured image snippet above at least once. The code in the snippet above is an example of functional programming paradigm implementation in Java, which will filter and transform the &lt;code&gt;List&amp;lt;String&amp;gt;&lt;/code&gt; in the request to another &lt;code&gt;List&amp;lt;String&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will write about how to write code using Java’s API for functional programming. In the end, we will write our own stream API so we can understand how to implement a functional programming style in Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functional Programming in Java
&lt;/h2&gt;

&lt;p&gt;Functional programming in Java has been around for a long time. When Oracle released Java 8 back in 2014, they introduced &lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html" rel="noopener noreferrer"&gt;lambda expression&lt;/a&gt;, which was the core feature for functional programming in Java.&lt;/p&gt;

&lt;p&gt;Let’s see an example of the difference between using a sequence of imperative statements and using a functional style in Java.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      List&amp;lt;String&amp;gt; stringList = Arrays.asList("Hello", "World", "How", "Are", "You", "Today");

        // imperative declaration
        List&amp;lt;String&amp;gt; filteredList = new ArrayList&amp;lt;&amp;gt;();

        for (String string: stringList) {
            if (string.equals("Hello") || string.equals("Are")) {
                filteredList.add(string);
            }
        }

        List&amp;lt;String&amp;gt; mappedList = new ArrayList&amp;lt;&amp;gt;();
        for (String string: filteredList) {
            mappedList.add(string + " String");
        }

        for (String string: mappedList) {
            System.out.println(string);
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Imperative Style







&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
        List&amp;lt;String&amp;gt; stringList = Arrays.asList("Hello", "World", "How", "Are", "You", "Today");

        //functional style
        stringList.stream()
                .filter(s -&amp;gt; s.equals("Hello") || s.equals("Are"))
                .map(s -&amp;gt; s + " String")
                .forEach(System.out::println);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
Functional Style





&lt;p&gt;As we can see, even though both pieces of code achieve the same result, the difference is significant. The imperative declaration code has many curly braces and is much longer, which makes it harder to read, compared to the functional style code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functional Interface Annotation
&lt;/h2&gt;

&lt;p&gt;To understand how functional programming works in Java, first we will need to look at the annotation included in Java 8 SDK, &lt;code&gt;@FunctionalInterface&lt;/code&gt;. We can look at it on the &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html" rel="noopener noreferrer"&gt;Java API documentation site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From the API documentation, we can see that the behaviors of a functional interface annotation in Java are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has exactly one abstract method in it.&lt;/li&gt;
&lt;li&gt;It can have more than one method, as long as there is only one abstract method.&lt;/li&gt;
&lt;li&gt;We can only add it to &lt;code&gt;Interface&lt;/code&gt; type.&lt;/li&gt;
&lt;li&gt;We can create the functional interface with a lambda expression, method references, or constructor references.&lt;/li&gt;
&lt;li&gt;We don’t need to define &lt;code&gt;@FunctionalInterface&lt;/code&gt; because the compiler will treat any interface meeting the definition of a functional interface as a functional interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a Functional Interface Class
&lt;/h2&gt;

&lt;p&gt;Now we know what a functional interface all about, we can create it by ourselves.&lt;/p&gt;

&lt;p&gt;Let’s first create a model called &lt;code&gt;Person&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.example.functional.programming.model;

public class Person {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person(String name) {
        this.name = name;
    }

    public static Person createClassExampleFromMethodReference(String name) {
        return new Person(name);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the functional interface, we’ll create &lt;code&gt;PersonFunctionalInterface&lt;/code&gt;class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.example.functional.programming.intf;

import com.example.functional.programming.model.Person;

@FunctionalInterface
public interface PersonFunctionalInterface {

    Person createPerson(String name);

    default String getDefaultMethodString() {
        return "Default Method";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that there are two methods in the interface, but since there is only one abstract method, &lt;code&gt;PersonFunctionalInterface&lt;/code&gt;class is valid as a functional interface.&lt;/p&gt;

&lt;p&gt;But suppose we define more than one abstract method, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.example.functional.programming.intf;

import com.example.functional.programming.model.Person;

@FunctionalInterface
public interface PersonFunctionalInterface {

    Person createPerson(String name);

    String mapStringToObject(String str);

    default String getDefaultMethodString() {
        return "Default Method";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will produce an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /D:/Project/functional/src/main/java/com/example/functional/programming/intf/PersonFunctionalInterface.java:[5,1] Unexpected @FunctionalInterface annotation
  com.example.functional.programming.intf.PersonFunctionalInterface is not a functional interface
    multiple non-overriding abstract methods found in interface com.example.functional.programming.intf.PersonFunctionalInterface
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.105 s
[INFO] Finished at: 2020-09-19T10:34:45+07:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project functional-programming: Compilation failure
[ERROR] /D:/Project/functional/src/main/java/com/example/functional/programming/intf/PersonFunctionalInterface.java:[5,1] Unexpected @FunctionalInterface annotation
[ERROR] com.example.functional.programming.intf.PersonFunctionalInterface is not a functional interface
[ERROR] multiple non-overriding abstract methods found in interface com.example.functional.programming.intf.PersonFunctionalInterface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using a Functional Interface
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Anonymous class
&lt;/h4&gt;

&lt;p&gt;Let’s first learn about the anonymous class. Java &lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html#:~:text=Anonymous%20classes%20enable%20you%20to,do%20not%20have%20a%20name" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; says that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically, with an anonymous class, we don’t have to define a class that implements the interface we made. We can create a class without a name and store it in a variable.&lt;/p&gt;

&lt;p&gt;Let’s declare an anonymous class as an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    @Test
    void declareAnonymousClass() {
        PersonFunctionalInterface anonClassExample = new PersonFunctionalInterface() {
            @Override
            public Person createPerson(String name) {
                return new Person(name);
            }
        };

        assert (anonClassExample.createPerson("Hello, World").getName().equals("Hello, World"));
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we’ve done here is we created an anonymous class with &lt;code&gt;PersonFunctionalInterface&lt;/code&gt; type and &lt;code&gt;anonClassExample&lt;/code&gt; name.&lt;/p&gt;

&lt;p&gt;We override the &lt;code&gt;createPerson&lt;/code&gt; abstract method so when we call the method, it will return a new Person object with a name.&lt;/p&gt;

&lt;p&gt;When we called &lt;code&gt;anonClassExample.createPerson(“Hello, World”)&lt;/code&gt;, we basically just created a new Person object with “Hello, World” as its name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Anonymous Class With a Functional Interface
&lt;/h2&gt;

&lt;p&gt;We can start creating the anonymous class of &lt;code&gt;PersonFunctionalinterface&lt;/code&gt; for the functional interface we made.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    void interfaceExample() {
        PersonFunctionalInterface normalAnonymousClass = new PersonFunctionalInterface() { // create normal anonymous class
            @Override
            public Person createPerson(String name) {
                return new Person(name);
            }
        };

        PersonFunctionalInterface interfaceExampleLambda = 
                name -&amp;gt; new Person(name); // create anonymous class by lambda
        PersonFunctionalInterface interfaceExampleMethodReference = 
                Person::createClassExampleFromMethodReference; // create anonymous class by method reference
        PersonFunctionalInterface interfaceExampleConstructorReference = 
                Person::new; // create anonymous class by constructor reference

        // assert that every anonymous class behave the same
        assert(normalAnonymousClass
                .createPerson("Hello, World").getName().equals("Hello, World"));
        assert(interfaceExampleLambda
                .createPerson("Hello, World").getName().equals("Hello, World"));
        assert(interfaceExampleMethodReference
                .createPerson("Hello, World").getName().equals("Hello, World"));
        assert(interfaceExampleConstructorReference
                .createPerson("Hello, World").getName().equals("Hello, World"));
        assert(normalAnonymousClass.getDefaultMethodString().equals("Default Method"));
        assert(interfaceExampleLambda.getDefaultMethodString().equals("Default Method"));
        assert(interfaceExampleMethodReference.getDefaultMethodString().equals("Default Method"));
        assert(interfaceExampleConstructorReference.getDefaultMethodString().equals("Default Method"));
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve just implemented the functional interface!&lt;/p&gt;

&lt;p&gt;In the code above, we created three anonymous classes in different ways. Remember that the anonymous class has the behavior that we can create a functional interface with a lambda expression, method references, or constructor references.&lt;/p&gt;

&lt;p&gt;To make sure we created anonymous classes that behave the same, we assert every method in the interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-In Functional Interface in Java 8
&lt;/h2&gt;

&lt;p&gt;Java 8 has many built-in functional interface classes in the &lt;code&gt;java.util.function&lt;/code&gt; package that we can see in &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html" rel="noopener noreferrer"&gt;its documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will only explain four of the most commonly used functional interfaces, but if you’re interested in more, you can read it in the Java API documentation noted above.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Consumer&amp;lt;T&amp;gt;&lt;/code&gt;: A functional interface that accepts an object and returns nothing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Producer&amp;lt;T&amp;gt;&lt;/code&gt;: A functional interface that accepts nothing and returns an object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt;: A functional interface that accepts an object and returns a boolean.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Function&amp;lt;T, R&amp;gt;&lt;/code&gt;: A functional interface that accepts an object and returns another object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Usage
&lt;/h2&gt;

&lt;p&gt;If you’ve been developing with Java a lot, then it’s likely you’ve met the concept of functional interface already.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stream and optional API
&lt;/h3&gt;

&lt;p&gt;Java’s Stream API uses functional interfaces a lot, as we can see in the code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    void commonFunctionalInterface() {
        Stream.of("Hello", "World", "How", "Are", "you")
                .filter(s -&amp;gt; s.equals("Hello") || s.equals("Are"))
                .map(s -&amp;gt; s + " String")
                .forEach(System.out::println);

        Optional.of("Hello")
                .filter(s -&amp;gt; s.equals("Hello") || s.equals("Are"))
                .map(s -&amp;gt; s + " String")
                .ifPresent(System.out::println);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;filter&lt;/code&gt; method has a parameter &lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt; functional interface. As we can see, the method accepts a &lt;code&gt;String&lt;/code&gt; and produce a &lt;code&gt;boolean&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;map&lt;/code&gt;method uses &lt;code&gt;Function&amp;lt;T, R&amp;gt;&lt;/code&gt; as its parameter. It accepts a &lt;code&gt;String&lt;/code&gt; and also returns &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;forEach&lt;/code&gt; method in Stream and &lt;code&gt;ifPresent&lt;/code&gt; method in Optional accept &lt;code&gt;Consumer&amp;lt;T&amp;gt;&lt;/code&gt;, accepting a &lt;code&gt;String&lt;/code&gt; and not returning anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reactive library
&lt;/h3&gt;

&lt;p&gt;Both of the most popular Java Reactive libraries, &lt;a href="https://github.com/ReactiveX/RxJava/wiki#:~:text=RxJava%20is%20a%20Java%20VM,programs%20by%20using%20observable%20sequences." rel="noopener noreferrer"&gt;RxJava&lt;/a&gt; and &lt;a href="https://projectreactor.io/" rel="noopener noreferrer"&gt;Reactor&lt;/a&gt;, are based on Java 8 Streams API, which means they also use functional interfaces in their code.&lt;/p&gt;

&lt;p&gt;If we look at &lt;a href="https://projectreactor.io/docs/core/release/api/" rel="noopener noreferrer"&gt;Reactor’s Flux API documentation&lt;/a&gt; and &lt;a href="http://reactivex.io/RxJava/javadoc/" rel="noopener noreferrer"&gt;RxJava’s Observable API documentation&lt;/a&gt;, we can see many of their methods accept a functional interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Our Own Stream API
&lt;/h2&gt;

&lt;p&gt;Now that we know how to create and use a functional interface, let’s try creating our own streaming API so we can understand how we can implement the functional interface.&lt;/p&gt;

&lt;p&gt;Of course, our streaming API is much simpler than Java’s.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.example.functional.intf;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class SimpleStream&amp;lt;T&amp;gt; {

    private List&amp;lt;T&amp;gt; values;

    public SimpleStream(T... values) {
        this.values = Arrays.asList(values);
    }

    public SimpleStream(List&amp;lt;T&amp;gt; values) {
        this.values = values;
    }

    public SimpleStream&amp;lt;T&amp;gt; filter(Predicate&amp;lt;T&amp;gt; filter) {
        List&amp;lt;T&amp;gt; returnValueList = new ArrayList&amp;lt;&amp;gt;();
        for (T value : values) {
            if (filter.test(value)) {
                returnValueList.add(value);
            }
        }
        this.values = returnValueList;
        return this;
    }

    public SimpleStream&amp;lt;T&amp;gt; map(Function&amp;lt;T, T&amp;gt; function) {
        List&amp;lt;T&amp;gt; returnValueList = new ArrayList&amp;lt;&amp;gt;();
        for (T value : values) {
            returnValueList.add(function.apply(value));
        }
        this.values = returnValueList;
        return this;
    }

    public void forEach(Consumer&amp;lt;T&amp;gt; consumer) {
        for (T value : values) {
            consumer.accept(value);
        }
    }

    public List&amp;lt;T&amp;gt; toList() {
        return this.values;
    }

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

&lt;/div&gt;



&lt;p&gt;And test class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    void implementingFunctionalInterface() {
        List&amp;lt;String&amp;gt; stringsFromSimpleStream = new SimpleStream&amp;lt;&amp;gt;("Hello", "World", "How", "Are", "you")
                .filter(s -&amp;gt; s.equals("Hello") || s.equals("Are"))
                .map(s -&amp;gt; s + " String")
                .toList();

        assert(stringsFromSimpleStream.size() == 2);
        assert(stringsFromSimpleStream.get(0).equals("Hello String"));
        assert(stringsFromSimpleStream.get(1).equals("Are String"));

        new SimpleStream&amp;lt;&amp;gt;(stringsFromSimpleStream)
                .forEach(System.out::println);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, let’s discuss the methods one by one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constructor
&lt;/h3&gt;

&lt;p&gt;We made two constructors, one constructor imitating the &lt;code&gt;Stream.of()&lt;/code&gt; API and one constructor to convert &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; to &lt;code&gt;SimpleStream&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filter
&lt;/h3&gt;

&lt;p&gt;In this method, we accept &lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt; as a parameter since &lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt;has an abstract parameter named &lt;code&gt;test&lt;/code&gt; that accepts an object and produces a boolean.&lt;/p&gt;

&lt;p&gt;Let’s look at the test class, where we wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.filter(s -&amp;gt; s.equals("Hello") || s.equals("Are"))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we wrote an anonymous class implementing &lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Predicate&amp;lt;String&amp;gt; filter = new Predicate&amp;lt;String&amp;gt;() {
            @Override
            public boolean test(String s) {
                return s.equals("Hello") || s.equals("Are");
            }
        };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So in the &lt;code&gt;SimpleStream&amp;lt;T&amp;gt;&lt;/code&gt; class, we can see the filter method as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    public SimpleStream&amp;lt;T&amp;gt; filter(Predicate&amp;lt;T&amp;gt; filter) {
        List&amp;lt;T&amp;gt; returnValueList = new ArrayList&amp;lt;&amp;gt;();
        for (T value : values) {
            if (value.equals("Hello") || value.equals("Are")) {
                returnValueList.add(value);
            }
        }
        this.values = returnValueList;
        return this;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Map
&lt;/h3&gt;

&lt;p&gt;In the map method, we accept &lt;code&gt;Function&amp;lt;T, R&amp;gt;&lt;/code&gt; as its parameter, which means the map method will accept a functional interface that accepts an object and also produces an object.&lt;/p&gt;

&lt;p&gt;We wrote the following in the test class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.map(s -&amp;gt; s + " String")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s the same as creating an anonymous class implementing &lt;code&gt;Function&amp;lt;T, R&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
        Function&amp;lt;String, String&amp;gt; map = new Function&amp;lt;String, String&amp;gt;() {
            @Override
            public String apply(String s) {
                return s + " String";
            }
        };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the &lt;code&gt;SimpleStream&amp;lt;T&amp;gt;&lt;/code&gt; class, we can see it as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public SimpleStream&amp;lt;T&amp;gt; map(Function&amp;lt;T, T&amp;gt; function) {
        List&amp;lt;T&amp;gt; returnValueList = new ArrayList&amp;lt;&amp;gt;();
        for (T value : values) {
            returnValueList.add(value + " String");
        }
        this.values = returnValueList;
        return this;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  forEach
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;forEach&lt;/code&gt; method accepts &lt;code&gt;Consumer&amp;lt;T&amp;gt;&lt;/code&gt; as its parameter, meaning that it will accept an object and return nothing.&lt;/p&gt;

&lt;p&gt;We wrote the following in the test class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.forEach(System.out::println);

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

&lt;/div&gt;



&lt;p&gt;This translates to creating an anonymous class implementing &lt;code&gt;Consumer&amp;lt;T&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Consumer&amp;lt;String&amp;gt; forEach = new Consumer&amp;lt;String&amp;gt;() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;SimpleStream&amp;lt;T&amp;gt;&lt;/code&gt;, we can see the &lt;code&gt;forEach&lt;/code&gt; method, as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
public void forEach(Consumer&amp;lt;T&amp;gt; consumer) {
        for (T value : values) {
            System.out.println(value);
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;With the release of Java 8 back in 2014, we can use a functional programming style in Java. Using a functional programming style in Java has many benefits, one of which is making your code shorter and more readable. With the benefits it provides, knowing the implementation of functional programming in Java if you’re a Java developer is a must!&lt;/p&gt;

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

&lt;p&gt;You can find the GitHub repository used for this article here:&lt;br&gt;
(&lt;a href="https://github.com/brilianfird/java-functional-programming" rel="noopener noreferrer"&gt;https://github.com/brilianfird/java-functional-programming&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amitph.com/java-method-and-constructor-reference/#:~:text=Constructor%20Reference%20is%20used%20to,assign%20to%20a%20target%20type" rel="noopener noreferrer"&gt;https://www.amitph.com/java-method-and-constructor-reference/#:~:text=Constructor%20Reference%20is%20used%20to,assign%20to%20a%20target%20type&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://reactivex.io/RxJava/javadoc/" rel="noopener noreferrer"&gt;http://reactivex.io/RxJava/javadoc/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://projectreactor.io/docs/core/release/api/" rel="noopener noreferrer"&gt;https://projectreactor.io/docs/core/release/api/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>java</category>
      <category>tutorials</category>
    </item>
    <item>
      <title>Avoiding the Null Pointer Exception With Optional in Java</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Tue, 08 Dec 2020 14:03:58 +0000</pubDate>
      <link>https://dev.to/brilianfird/avoiding-the-null-pointer-exception-with-optional-in-java-224i</link>
      <guid>https://dev.to/brilianfird/avoiding-the-null-pointer-exception-with-optional-in-java-224i</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fotc56mldg9g0vhyk59do.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fotc56mldg9g0vhyk59do.jpg" alt="Avoiding the Null Pointer Exception With Optional in Java" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 1964, British computer scientist Tony Hoare invented the Null Pointer References.&lt;/p&gt;

&lt;p&gt;The Null Pointer Exception has contributed the most bugs in production exceptions. It was implemented in many programming languages, including C, C++, C#, JavaScript, Java, and more.&lt;/p&gt;

&lt;p&gt;The loss of financial resources, time, and human resources to fix it prompted Hoare to call it a “&lt;a href="https://qconlondon.com/london-2009/qconlondon.com/london-2009/speaker/Tony+Hoare.html" rel="noopener noreferrer"&gt;billion-dollar mistake&lt;/a&gt;.”&lt;/p&gt;

&lt;p&gt;Java is one of the programming languages that implement Null Pointer References. If you’ve been developing with Java, I’m sure that you’ve seen them a lot. It doesn’t matter if you are new to Java or have ten years of experience. There is always a chance that you’ll encounter a Null Pointer Exception bug.&lt;/p&gt;




&lt;h2&gt;
  
  
  Optional in Java
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Optional&lt;/code&gt; is an API that was introduced in Java 8. If used right, it can solve the problem of the Null Pointer Exception.&lt;/p&gt;

&lt;p&gt;Optional API implements functional programming and uses Functional Interface.&lt;/p&gt;

&lt;p&gt;If you want to know more about Functional Programming in Java you can read my other article, &lt;a href="https://codecurated.com/blog/functional-programming-in-java-explained/" rel="noopener noreferrer"&gt;Functional Programming in Java, Explained&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before we proceed any further, please note that I’m using Java 11 for the examples in this article. If you’re using a different version of Java, some methods might not exist or behave exactly the same.&lt;/p&gt;




&lt;h2&gt;
  
  
  Empty Optional
&lt;/h2&gt;

&lt;p&gt;An empty &lt;code&gt;optional&lt;/code&gt; is the main way to avoid the Null Pointer Exception when using the &lt;code&gt;Optional&lt;/code&gt; API.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Optional&lt;/code&gt;’s flow, a null will be transformed into an empty &lt;code&gt;Optional&lt;/code&gt;. The empty &lt;code&gt;Optional&lt;/code&gt; won’t be processed any further. This is how we can avoid a &lt;code&gt;NullPointerException&lt;/code&gt; when using &lt;code&gt;Optional&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will learn further about how an empty &lt;code&gt;Optional&lt;/code&gt; behaves later in this article.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Optional object
&lt;/h2&gt;

&lt;p&gt;There are three ways to initiate an &lt;code&gt;Optional&lt;/code&gt; object:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Optional.of(T)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Optional.ofNullable(T)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Optional.empty()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Optional.of
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Optional.of&lt;/code&gt; accepts any type with a non-nullable value in its parameter. To create an &lt;code&gt;Optional&lt;/code&gt; object with &lt;code&gt;Optional.of&lt;/code&gt;, we just have to pass a value in its parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void initializeOptional_optionalOf() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.of("Hello, world");
        assert helloWorldOptional.isPresent();
        assert "Hello, world".equals(helloWorldOptional.get());
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be very careful when you are passing a value to the &lt;code&gt;Optional.of&lt;/code&gt;. Remember that &lt;code&gt;Optional.of&lt;/code&gt; doesn’t accept null values in its parameter. If you try to pass a null value, it will produce a &lt;code&gt;NullPointerException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     @Test
    public void initializeOptional_optionalOf_null() {
        try {
            Optional.of(null);
        } catch (Exception e) {
            assert e instanceof NullPointerException;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optional.ofNullable
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Optional.ofNullable&lt;/code&gt; is similar to Optional.of. It accepts any type. The difference is, with &lt;code&gt;Optional.ofNullable&lt;/code&gt;, you can pass a null value to its parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void initializeOptional_optionalOfNullable() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.ofNullable("Hello, world");
        assert helloWorldOptional.isPresent();
        assert "Hello, world".equals(helloWorldOptional.get());
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;Optional.ofNullable&lt;/code&gt; is initialized using a null object, it will return an empty &lt;code&gt;Optional&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void initializeOptional_optionalOfNullable_null() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.ofNullable(null);
        assert !helloWorldOptional.isPresent();
        try {
            helloWorldOptional.get();
        } catch (Exception e) {
            assert e instanceof NoSuchElementException;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optional.empty
&lt;/h3&gt;

&lt;p&gt;An empty &lt;code&gt;Optional&lt;/code&gt; can be initialized by using &lt;code&gt;Optional.empty()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void initializeOptional_optionalEmpty() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.empty();
        assert !helloWorldOptional.isPresent();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accessing Optional
&lt;/h2&gt;

&lt;p&gt;There are some ways to get the value of an Optional.&lt;/p&gt;

&lt;h3&gt;
  
  
  get
&lt;/h3&gt;

&lt;p&gt;A pretty straightforward method. The &lt;code&gt;get&lt;/code&gt; method will return the value of &lt;code&gt;Optional&lt;/code&gt; if it is present and throw a &lt;code&gt;NoSuchElementException&lt;/code&gt; if the value doesn’t exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void get_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.of("Hello, World");
        assert "Hello, World".equals(helloWorldOptional.get());
    }

    @Test
    public void get_null_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.empty();
        try {
            helloWorldOptional.get();
        } catch (Exception e) {
            assert e instanceof NoSuchElementException;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  orElse
&lt;/h3&gt;

&lt;p&gt;If you want to use a default value if the &lt;code&gt;Optional&lt;/code&gt; is empty, you can use the &lt;code&gt;orElse&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void orElse_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.of("Hello, World");
        assert "Hello, World".equals(helloWorldOptional.orElse("default"));
    }

    @Test
    public void orELseNull_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.empty();
        assert "default".equals(helloWorldOptional.orElse("default"));
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  orElseGet
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;orElseGet&lt;/code&gt; is very similar to the &lt;code&gt;orElse&lt;/code&gt; method. It’s just that &lt;code&gt;orElseGet&lt;/code&gt; accepts &lt;code&gt;Supplier&amp;lt;T&amp;gt;&lt;/code&gt; as its parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void orElseGet_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.of("Hello, World");
        assert "Hello, World".equals(helloWorldOptional.orElseGet(() -&amp;gt;"default"));
    }

    @Test
    public void orELseGet_Null_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.empty();
        assert "default".equals(helloWorldOptional.orElseGet(() -&amp;gt;"default"));
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  orElseThrow
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;orElseThrow&lt;/code&gt; will return the value of the &lt;code&gt;Optional&lt;/code&gt; or throw an exception if the value of the &lt;code&gt;Optional&lt;/code&gt; is empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void orElseThrow_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.of("Hello, World");
        assert "Hello, World".equals(helloWorldOptional.orElseThrow(NullPointerException::new));
    }

    @Test
    public void orELseThrow_Null_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.empty();
        try {
            helloWorldOptional.orElseThrow(NullPointerException::new);
        } catch (Exception e) {
            assert e instanceof NullPointerException;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Processing an Optional
&lt;/h2&gt;

&lt;p&gt;There are many ways to process and transform an &lt;code&gt;Optional&lt;/code&gt;. In this section, we will learn the common methods that are used.&lt;/p&gt;

&lt;p&gt;As I wrote at the beginning of the article, an empty &lt;code&gt;Optional&lt;/code&gt; won’t be processed in the flow. We can see that from the examples in this section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Map
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;map&lt;/code&gt; is the most used method when processing an &lt;code&gt;Optional&lt;/code&gt; object. It accepts &lt;code&gt;Function&amp;lt;? super T, ? extends U&amp;gt;&lt;/code&gt; as its parameter and returns an &lt;code&gt;Optional&amp;lt;U&amp;gt;.&lt;/code&gt; This means you can use a Function with any type of parameter and the return value will be wrapped to &lt;code&gt;Optional&lt;/code&gt; in the &lt;code&gt;map&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void processingOptional_map_test() {
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of("Hello, World")
                .map(a -&amp;gt; a + ", Hello");

        assert stringOptional.isPresent();
        assert "Hello, World, Hello".equals(stringOptional.get());
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to return a null value in &lt;code&gt;Function&amp;lt;? super T, ? extends U&amp;gt;&lt;/code&gt;, the &lt;code&gt;map&lt;/code&gt; method will return an empty &lt;code&gt;Optional&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void processingOptional_map_empty_test() {
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of("Hello, World")
                .map(a -&amp;gt; null);

        assert !stringOptional.isPresent();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An empty optional won’t be processed by &lt;code&gt;map&lt;/code&gt;. We can confirm this with the following test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void processingOptional_map_empty_notProcessed_test() {
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of("Hello, World")
                .map(a -&amp;gt; null)
                .map(a -&amp;gt; {
                    atomicBoolean.set(true);
                    return "won't be processed";
                });

        assert !stringOptional.isPresent();
        assert atomicBoolean.get() == false;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  FlatMap
&lt;/h3&gt;

&lt;p&gt;This is similar to &lt;code&gt;map&lt;/code&gt;, but &lt;code&gt;flatMap&lt;/code&gt; won’t wrap the return value of the Function to &lt;code&gt;Optional&lt;/code&gt;. The &lt;code&gt;flatMap&lt;/code&gt; method accepts &lt;code&gt;Function&amp;lt;? super T, ? extends Optional&amp;lt;? extends U&amp;gt;&amp;gt;&lt;/code&gt; as its parameter. This means that you’ll need to define a Function that accepts any type and returns an &lt;code&gt;Optional&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You will usually use the &lt;code&gt;flatMap&lt;/code&gt; method when your code calls another method that returns an &lt;code&gt;Optional&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    @Test
    public void processingOptional_flatmap_test() {
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of("Hello, World")
                .flatMap(this::getString);

        assert "Hello, World, Hello".equals(stringOptional.get());
    }

    @Test
    public void processingOptional_flatmap_randomString_test() {
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of(UUID.randomUUID().toString())
                .flatMap(this::getString);

        assert !stringOptional.isPresent();
    }

    public Optional&amp;lt;String&amp;gt; getString(String s) {
        if ("Hello, World".equals(s)) {
            return Optional.of("Hello, World, Hello");
        }
        return Optional.empty();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Filter
&lt;/h3&gt;

&lt;p&gt;In the previous example of &lt;code&gt;flatMap&lt;/code&gt;, we used a declarative style to differentiate the return value of the &lt;code&gt;getString&lt;/code&gt; method. But we can actually use a functional style for that with the &lt;code&gt;filter&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   @Test
    public void processingOptional_filter_test() {
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of("Hello, World")
                .filter(helloWorldString -&amp;gt; "Hello, World".equals(helloWorldString))
                .map(helloWorldString -&amp;gt; helloWorldString + ", Hello");

        assert "Hello, World, Hello".equals(stringOptional.get());
    }

    @Test
    public void processingOptional_filter_randomString_test() {
        Optional&amp;lt;String&amp;gt; stringOptional = Optional.of(UUID.randomUUID().toString())
                .filter(helloWorldString -&amp;gt; "Hello, World".equals(helloWorldString))
                .map(helloWorldString -&amp;gt; helloWorldString + ", Hello");

        assert !stringOptional.isPresent();
    }
view rawProcessingOptionalT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If Present
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ifPresent&lt;/code&gt; method accepts a &lt;code&gt;Consumer&lt;/code&gt; that will only be executed if the Optional is not empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void processingOptional_ifPresent_test() {
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
        Optional.of("Hello, World")
            .ifPresent(helloWorldString -&amp;gt; atomicBoolean.set(true));
        assert atomicBoolean.get();
    }

    @Test
    public void processingOptional_ifPresent_empty_test() {
        AtomicBoolean atomicBoolean = new AtomicBoolean(false);
        Optional.empty()
                .ifPresent(helloWorldString -&amp;gt; atomicBoolean.set(true));
        assert !atomicBoolean.get();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Things to avoid
&lt;/h2&gt;

&lt;p&gt;There are some critical things that you need to avoid if you want to use &lt;code&gt;Optional&lt;/code&gt; in your code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don’t create a method that accepts Optional
&lt;/h3&gt;

&lt;p&gt;Creating a method that accepts &lt;code&gt;Optional&lt;/code&gt; as a parameter might introduce a problem it wants to solve, &lt;code&gt;NullPointerException&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If a person using the method with the &lt;code&gt;Optional&lt;/code&gt; parameter is not aware of it, they might pass a null to the method instead of &lt;code&gt;Optional.empty()&lt;/code&gt;. Processing a &lt;code&gt;null&lt;/code&gt; will produce a &lt;code&gt;NullPointerException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void optionalAsParameter_test() {
        try {
            isPhoneNumberPresent(null);
        } catch (Exception e) {
            assert e instanceof NullPointerException;
        }
    }

    public boolean isPhoneNumberPresent(Optional&amp;lt;String&amp;gt; phoneNumber) {
        return phoneNumber.isPresent();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Getting value without checking
&lt;/h3&gt;

&lt;p&gt;If you’re using &lt;code&gt;Optional&lt;/code&gt;, then you should avoid using the get method if you can. If you still want to use it for some reason, make sure that you check it with the &lt;code&gt;isPresent&lt;/code&gt; method first because if you use get on an empty &lt;code&gt;Optional&lt;/code&gt;, it will produce a &lt;code&gt;NoSuchMethodException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Test
    public void getWithIsPresent_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.ofNullable(null);
        if (helloWorldOptional.isPresent()) {
            System.out.println(helloWorldOptional.get());
        }
    }

    @Test
    public void getWithoutIsPresent_error_test() {
        Optional&amp;lt;String&amp;gt; helloWorldOptional = Optional.ofNullable(null);
        try {
            System.out.println(helloWorldOptional.get());
        } catch (Exception e) {
            assert e instanceof NoSuchElementException;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Thank you for reading until the end! Optional is a powerful feature that every Java developer should know about. If you use optional features from end to end correctly, then I’m sure that you won’t meet the &lt;code&gt;NullPointerException&lt;/code&gt; anymore.&lt;/p&gt;

&lt;p&gt;Optional is also used as a base for other big libraries like Reactor and RXJava, so knowing how Optional works will help you understand them too.&lt;/p&gt;

&lt;p&gt;You can find the repository with the examples in this article below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/brilianfird/java-optional" rel="noopener noreferrer"&gt;https://github.com/brilianfird/java-optional&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;References&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://codecurated.com/p/5ab1a3fc-adaf-415e-a4f5-1f6c6f4c2bdb/References%20Null%20Pointer%20References:%20The%20Billion%20Dollar%20Mistake%20https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions%20https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html" rel="noopener noreferrer"&gt;Null Pointer References: The Billion Dollar Mistake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Handle Typos in Elasticsearch Using Fuzzy Query</title>
      <dc:creator>Brilian Firdaus</dc:creator>
      <pubDate>Thu, 03 Dec 2020 12:41:14 +0000</pubDate>
      <link>https://dev.to/brilianfird/how-to-handle-typos-in-elasticsearch-using-fuzzy-query-37o6</link>
      <guid>https://dev.to/brilianfird/how-to-handle-typos-in-elasticsearch-using-fuzzy-query-37o6</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphfrnbv72fgji9n0mr0d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphfrnbv72fgji9n0mr0d.jpg" alt="How to Handle Typos in Elasticsearch Using Fuzzy Query" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Typo is something that often happens and can reduce user’s experience, fortunately, Elasticsearch can handle it easily with Fuzzy Query.&lt;/p&gt;

&lt;p&gt;Handling typos is a must if you’re building an advanced autocomplete system with the Elasticsearch.&lt;/p&gt;

&lt;p&gt;If you want to create a simple one instead, you can read my other articles “&lt;a href="https://codecurated.com/blog/create-a-simple-autocomplete-with-elasticsearch/" rel="noopener noreferrer"&gt;Create a Simple Autocomplete With Elasticsearch&lt;/a&gt;“.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is fuzzy logic
&lt;/h2&gt;

&lt;p&gt;Fuzzy logic is a mathematics logic in which the truth of variables might be any number between 0 and 1. It is different with a Boolean logic that only has the truth values either 0 or 1.&lt;/p&gt;

&lt;p&gt;In the Elasticsearch, fuzzy query means the terms in the queries don’t have to be the exact match with the terms in the Inverted Index.&lt;/p&gt;

&lt;p&gt;To calculate the distance between query, Elasticsearch uses &lt;a href="https://en.wikipedia.org/wiki/Levenshtein_distance" rel="noopener noreferrer"&gt;Levenshtein Distance Algorithm&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to calculate distance using Levenshtein Distance Algorithm
&lt;/h2&gt;

&lt;p&gt;Calculating a distance with Levenshtein Distance Algorithm is easy.&lt;/p&gt;

&lt;p&gt;You just need to compare the first and second word character by character.&lt;/p&gt;

&lt;p&gt;If the character is different, then you can add the distance between the words by one.&lt;/p&gt;

&lt;p&gt;Let’s see an example, how to calculate the distance between the common typo word &lt;code&gt;“Gppgle”&lt;/code&gt; with the correct word &lt;code&gt;“Google”&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwn9jtg0uwhcbao4fxz9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwn9jtg0uwhcbao4fxz9v.png" alt="How to Handle Typos in Elasticsearch Using Fuzzy Query" width="290" height="122"&gt;&lt;/a&gt;elasticsearch fuzzy query: Levenshtein distance&lt;/p&gt;

&lt;p&gt;After we calculate the distance between &lt;code&gt;“Gppgle”&lt;/code&gt; and &lt;code&gt;“Google”&lt;/code&gt; with Levenshtein Distance Algorithm, we can see that the distance is 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fuzzy Query in Elasticsearch
&lt;/h2&gt;

&lt;p&gt;Handling typo in Elasticsearch with Fuzzy Query is also simple.&lt;/p&gt;

&lt;p&gt;Let’s start with making an example of the typo word &lt;code&gt;“Gppgle”&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match" : {
            "text": {
                "query": "gppgle"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  }
}

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

&lt;/div&gt;



&lt;p&gt;When we’re using normal Match Query, the Elasticsearch will analyze the query &lt;code&gt;“gppgle”&lt;/code&gt; first before searching it into the Elasticsearch.&lt;/p&gt;

&lt;p&gt;The only term in the inverted index is “google” and it doesn’t match the term &lt;code&gt;“gppgle”&lt;/code&gt;. Therefore, the Elasticsearch won’t return any result.&lt;/p&gt;

&lt;p&gt;Now, let’s try Elasticsearch’s fuzzy in Match Query&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match" : {
            "text": {
                "query": "gppgle",
                "fuzziness": "AUTO"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 8,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.19178805,
    "hits": [
      {
        "_index": "fuzzy-query",
        "_type": "_doc",
        "_id": "w8YOCXUBHf9qB4Apc0Cz",
        "_score": 0.19178805,
        "_source": {
          "text": "google"
        }
      }
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;As you can see, with fuzzy, the Elasticsearch returned a response.&lt;/p&gt;

&lt;p&gt;We’ve learnt in the before that &lt;code&gt;“gppgle”&lt;/code&gt; and &lt;code&gt;“google”&lt;/code&gt; have the distance of 2.&lt;/p&gt;

&lt;p&gt;In the query, we inserted &lt;code&gt;“fuzziness”:"AUTO"&lt;/code&gt; instead of a number. Why is it working?&lt;/p&gt;

&lt;p&gt;Elasticsearch will determine what fuzziness distance is appropriate if we use &lt;code&gt;“AUTO”&lt;/code&gt; value in the &lt;code&gt;“fuzziness”&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;For 6 characters, the Elasticsearch by default will allow 2 edit distance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;“AUTO”&lt;/code&gt; fuzziness is preferable, but you can tune it with an exact number if you want to.&lt;/p&gt;

&lt;p&gt;Now, let’s try with an exact number to prove that &lt;code&gt;“gppgle”&lt;/code&gt; and &lt;code&gt;“google”&lt;/code&gt; have a distance of 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gppgle and google with fuzziness 1&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url 'http://localhost:9200/fuzzy-query/_doc/_search?explain=true' \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match" : {
            "text": {
                "query": "gppgle",
                "fuzziness": "1"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
No Response&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gppgle and google with fuzziness 2&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match" : {
            "text": {
                "query": "gppgle",
                "fuzziness": "2"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.19178805,
    "hits": [
      {
        "_index": "fuzzy-query",
        "_type": "_doc",
        "_id": "w8YOCXUBHf9qB4Apc0Cz",
        "_score": 0.19178805,
        "_source": {
          "text": "google"
        }
      }
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;When we use &lt;code&gt;“fuzziness”:"1"&lt;/code&gt;, no result is returned by the Elasticsearch.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;“fuzziness”:"2"&lt;/code&gt;, though, the Elasticsearch returned the document &lt;code&gt;“google”&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This proves our previous distance calculation of &lt;code&gt;“gppgle”&lt;/code&gt; and &lt;code&gt;“google”&lt;/code&gt; with Levenshtein Distance Algorithm, in which the result is 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two types of a fuzzy query in Elasticsearch
&lt;/h2&gt;

&lt;p&gt;In the previous example, we use a fuzzy query as a parameter inside Match Query.&lt;/p&gt;

&lt;p&gt;But there is another way to use the fuzzy feature, Fuzzy Query.&lt;/p&gt;

&lt;p&gt;Seems to be the same! So, what’s the difference between them?&lt;/p&gt;

&lt;p&gt;Before continuing, if you want to understand more about analyzer, you can read my other articles “Elasticsearch: Text vs. Keyword“.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fuzzy Query
&lt;/h3&gt;

&lt;p&gt;Fuzzy Query works like just Term Query, the query to Elasticsearch is not analyzed and used raw to search the Inverted Index.&lt;/p&gt;

&lt;p&gt;For example, let’s index one more document &lt;code&gt;“Hong Kong”&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc \
  --header 'content-type: application/json' \
  --data '{
    "text":"Hong Kong"
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_index": "fuzzy-query",
  "_type": "_doc",
  "_id": "5sbKDXUBHf9qB4ApJUDr",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

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

&lt;/div&gt;



&lt;p&gt;Let’s look on what terms the analyzer produces with Elasticsearch’s Analyze API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/_analyze \
  --header 'content-type: application/json' \
  --data '{
    "analyzer": "standard",
    "text": "Hong Kong"
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "tokens": [
    {
      "token": "hong",
      "start_offset": 0,
      "end_offset": 4,
      "type": "&amp;lt;ALPHANUM&amp;gt;",
      "position": 0
    },
    {
      "token": "kong",
      "start_offset": 5,
      "end_offset": 9,
      "type": "&amp;lt;ALPHANUM&amp;gt;",
      "position": 1
    }
  ]
}

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

&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;standard_analyzer&lt;/code&gt; produce two terms, &lt;code&gt;“hong”&lt;/code&gt; and &lt;code&gt;“kong”&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you read my other article "&lt;a href="https://codecurated.com/blog/elasticsearch-text-vs-keyword/" rel="noopener noreferrer"&gt;Elasticsearch: Text vs. Keyword&lt;/a&gt;", you’d know that if we use a term query to search “Hong Kong” then we won’t get any result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "fuzzy" : {
            "text": {
                "value": "Hpng Kpng",
                "fuzziness": "2"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  }
}

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

&lt;/div&gt;



&lt;p&gt;This is because there is no term that has less than 2 edit distance with &lt;code&gt;“Hong Kong”&lt;/code&gt; in the Elasticsearch.&lt;/p&gt;

&lt;p&gt;Now, Let’s try Fuzzy Query with &lt;code&gt;“Hpng”&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "fuzzy" : {
            "text": {
                "value": "HPng",
                "fuzziness": "2"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.60996956,
    "hits": [
      {
        "_index": "fuzzy-query",
        "_type": "_doc",
        "_id": "5sbKDXUBHf9qB4ApJUDr",
        "_score": 0.60996956,
        "_source": {
          "text": "Hong Kong"
        }
      }
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;Term &lt;code&gt;“Hpng”&lt;/code&gt; in the query and the term &lt;code&gt;“hong”&lt;/code&gt; in the Elasticsearch have a distance of two.&lt;/p&gt;

&lt;p&gt;Remember that the term queried and the term in the inverted index is case-sensitive, the distance “2” comes from the difference between &lt;code&gt;“Hp”&lt;/code&gt; and &lt;code&gt;“ho”&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Match Query with Fuzziness parameter
&lt;/h4&gt;

&lt;p&gt;Match Query with fuzziness parameter is more preferable than Fuzzy Query. The analyzer in the query will analyze your query before searching it into the Inverted Index.&lt;/p&gt;

&lt;p&gt;Let’s try the same query as we did in the Fuzzy Query’s section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match": {
            "text": {
                "query": "Hpng Kong",
                "fuzziness": 2
            }
        }
    }
}'


curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match" : {
            "text": {
                "value": "HPng",
                "fuzziness": "2"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.762462,
    "hits": [
      {
        "_index": "fuzzy-query",
        "_type": "_doc",
        "_id": "5sbKDXUBHf9qB4ApJUDr",
        "_score": 0.762462,
        "_source": {
          "text": "Hong Kong"
        }
      }
    ]
  }
}

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

&lt;/div&gt;



&lt;p&gt;As expected, both queries returned a result!&lt;/p&gt;

&lt;p&gt;The first query, &lt;code&gt;“Hpng Kong”&lt;/code&gt; is analyzed into &lt;code&gt;“hpng”&lt;/code&gt; and &lt;code&gt;“kong”&lt;/code&gt;. Both terms &lt;code&gt;“hpng”&lt;/code&gt; and &lt;code&gt;“kong”&lt;/code&gt; exist in the Inverted Index.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;“hpng”&lt;/code&gt; and &lt;code&gt;“hong”&lt;/code&gt; matched with a distance of 1. While &lt;code&gt;“kong”&lt;/code&gt; and &lt;code&gt;“kong”&lt;/code&gt; match perfectly.&lt;/p&gt;

&lt;p&gt;One thing to note if you plan to use Match Query is that every of the terms in the query will allow fuzziness.&lt;/p&gt;

&lt;p&gt;We can try querying with &lt;code&gt;“hggg kggg”&lt;/code&gt; which has an edit distance of 4 with &lt;code&gt;“Hong Kong”&lt;/code&gt; using &lt;code&gt;“fuzziness”:2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl --request POST \
  --url http://localhost:9200/fuzzy-query/_doc/_search \
  --header 'content-type: application/json' \
  --data '{
    "query": {
        "match": {
            "text": {
                "query": "hggg kggg",
                "fuzziness": "2"
            }
        }
    }
}'

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "_index": "fuzzy-query",
    "_type": "_doc",
    "_id": "5sbKDXUBHf9qB4ApJUDr",
    "_score": 1.2330425,
    "_source": {
        "text": "Hong Kong"
    }
}

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

&lt;/div&gt;



&lt;p&gt;As you can see, the Elasticsearch returned a result.&lt;/p&gt;

&lt;p&gt;This is because of the query &lt;code&gt;“hggg kggg”&lt;/code&gt; is analyzed to terms &lt;code&gt;“hggg”&lt;/code&gt; and &lt;code&gt;“kggg”&lt;/code&gt; by the analyzer.&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;“hggg”&lt;/code&gt; and &lt;code&gt;“kggg”&lt;/code&gt; respectively have the edit distance of 2 to &lt;code&gt;“hong”&lt;/code&gt; and &lt;code&gt;“kong”&lt;/code&gt; in the Elasticsearch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tuning the Fuzzy Query in Elasticsearch
&lt;/h2&gt;

&lt;p&gt;You can tune the Fuzzy Query to match your use case.&lt;/p&gt;

&lt;p&gt;In this section, I will write about the parameters that we can change in the query.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fuzziness
&lt;/h3&gt;

&lt;p&gt;Fuzziness is the heart of Fuzzy Query.&lt;/p&gt;

&lt;p&gt;The value that we pass to this parameter is the maximum distance allowed.&lt;/p&gt;

&lt;p&gt;There are two types of value that we can pass, an integer for exact maximum distance and &lt;code&gt;“AUTO”&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;“AUTO”&lt;/code&gt; value allows the fuzziness in the query to be dynamic.&lt;/p&gt;

&lt;p&gt;We can tune 2 parameters in the &lt;code&gt;“AUTO”&lt;/code&gt; value and write it as &lt;code&gt;“AUTO:[low],[high]”&lt;/code&gt;. The query will set fuzziness as 0 if the term length is below the low value. If the term length is between the low and high value, the query will set the fuzziness to 1. Last, If the term length is more than the high value, the query will set the fuzziness to 2.&lt;/p&gt;

&lt;p&gt;The Elasticsearch will use 3 and 6 as the default if the low and high value is not determined.&lt;/p&gt;

&lt;p&gt;Let’s use an example with a document “Fuzzy Query in Elasticsearch allows you to handle typos”.&lt;/p&gt;

&lt;p&gt;We can try some queries to prove the mechanism of AUTO we described earlier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;“tp”&lt;/code&gt;: 1 edit distance from &lt;code&gt;“to”&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;“Fyzzy”&lt;/code&gt;: 1 edit distance from &lt;code&gt;“Fuzzy”&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;“Fyzyy”&lt;/code&gt;: 2 edit distance from &lt;code&gt;“Fuzzy”&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;“Elastissearcc”&lt;/code&gt;: 2 edit distance from &lt;code&gt;“Fuzzy”&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;“Elestissearcc”&lt;/code&gt;: 3 edit distance from &lt;code&gt;“Fuzzy”&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After querying it, these queries produced a result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;“Fyzzy”&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;“Elastissearcc”&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The queries don’t:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;“tp”&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;“Fyzyy”&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;“Elestissearcc”&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Transpositions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;transpositions&lt;/code&gt; will allow your query to calculate the transpositions of two adjacent characters (ab -&amp;gt; ba) as 1 distance.&lt;/p&gt;

&lt;p&gt;For example, if we set the &lt;code&gt;transpositions&lt;/code&gt; to true, we will get a result if we query with &lt;code&gt;“leasticsearcc”&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But if we set it as false, there will be no result from the Elasticsearch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "query": {
    "fuzzy": {
      "text": {
        "value": "leasticsearcc",
        "fuzziness": "AUTO",
        "transpositions": true
      }
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "_index": "fuzzy-query",
    "_type": "_doc",
    "_id": "AsawDnUBHf9qB4ApNUFh",
    "_score": 0.5491282,
    "_source": {
        "text": "Fuzzy Query in Elasticsearch allows you to handle typos"
    }
}

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

&lt;/div&gt;



&lt;p&gt;The Elasticsearch defaults the &lt;code&gt;transpositions&lt;/code&gt; setting to true.&lt;/p&gt;

&lt;p&gt;We can’t set this setting to the Match Query. The Match Query will always calculate &lt;code&gt;transpositions&lt;/code&gt; as 1 distance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Max Expansions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;max_expansions&lt;/code&gt; will determine the maximum result you get from your query.&lt;/p&gt;

&lt;p&gt;If you set the &lt;code&gt;max_expansions&lt;/code&gt; to 1 and there is 2 document in the Elasticsearch that are appropriate to your query, the Elasticsearch will only return 1.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;max_expansions&lt;/code&gt; applies to shard level. So if you have many shards in the Elasticsearch, even if you set the &lt;code&gt;max_expansion&lt;/code&gt; to 1, the query might return more results.&lt;/p&gt;

&lt;p&gt;The default value for &lt;code&gt;max_expansions&lt;/code&gt; is 50.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefix Length
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;prefix_length&lt;/code&gt; is the number of prefix characters that is not considered in fuzzy query.&lt;/p&gt;

&lt;p&gt;For example, if we set the &lt;code&gt;prefix_length&lt;/code&gt; to 1, we won’t get any result if we query &lt;code&gt;“llasticsearch”&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The prefix_length setting defaults to 0.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rewrite
&lt;/h3&gt;

&lt;p&gt;You can change &lt;code&gt;rewrite&lt;/code&gt; parameter if you want to change the scoring of the results.&lt;/p&gt;

&lt;p&gt;You can find more information about the &lt;code&gt;rewrite&lt;/code&gt; parameter in the &lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-term-rewrite.html" rel="noopener noreferrer"&gt;Elasticsearch documentation&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Handling a typo in Elasticsearch is very easy and can improve the user’s experience.&lt;/p&gt;

&lt;p&gt;The simplest way to handle a typo is to just add &lt;code&gt;“fuzziness”:"AUTO"&lt;/code&gt; in your Match Query.&lt;/p&gt;

&lt;p&gt;If you want to tune the Query, there are some parameters that you can change with the &lt;code&gt;“fuzziness”&lt;/code&gt; being the most important.&lt;/p&gt;

&lt;p&gt;Thank you for reading until the end!&lt;/p&gt;

&lt;p&gt;Stay tune to my other articles about Elasticsearch!&lt;/p&gt;

</description>
      <category>elasticsearch</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
