<?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: Ashish Choudhary</title>
    <description>The latest articles on DEV Community by Ashish Choudhary (@yrashish).</description>
    <link>https://dev.to/yrashish</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%2F534226%2F7e57bd4f-6871-45e2-b5dc-40ff62c14a84.jpg</url>
      <title>DEV Community: Ashish Choudhary</title>
      <link>https://dev.to/yrashish</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yrashish"/>
    <language>en</language>
    <item>
      <title>Monitoring Spring Boot Applications: Part 1</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Fri, 07 Jan 2022 19:46:44 +0000</pubDate>
      <link>https://dev.to/yrashish/monitoring-spring-boot-applications-part-1-4fb1</link>
      <guid>https://dev.to/yrashish/monitoring-spring-boot-applications-part-1-4fb1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In part 1 of this series, we will learn about JDK Flight Recorder and how we can use it to monitor a Spring Boot application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Application monitoring is one thing that we as developers cannot overlook. It doesn’t matter if you run a monolith or microservices application because application monitoring is a must for production workloads to know what’s happening with your application. If you are using Spring Boot, there are different ways to&lt;br&gt;
monitor an application. The most popular way to monitor a Spring Boot application is to enable the &lt;a href="https://github.com/spring-projects/spring-boot/tree/v2.6.0/spring-boot-project/spring-boot-actuator" rel="noopener noreferrer"&gt;spring-boot-actuator&lt;/a&gt; module to achieve the desired result.&lt;/p&gt;

&lt;p&gt;More often than not, we rely on third-party tools like Appdynamics, Dynatrace, Prometheus, and Grafana to monitor our workloads. But what if I told you that you could use a tool that comes with JDK to monitor your Spring Boot applications. Could you not believe me yet? Let me introduce you to the JDK flight recorder in this article that we will use to monitor a Spring Boot application.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is a JDK Flight Recorder?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;JDK Flight Recorder is a diagnostic tool that collects events of running Java applications, JVM and OS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;JFR was a commercial feature earlier, but it has been open-sourced and made GA from OpenJDK 11 onwards. See this &lt;a href="https://openjdk.java.net/jeps/328" rel="noopener noreferrer"&gt;JEP&lt;/a&gt;. If you are stuck on JDK 8 like everyone else, then no worries as it seems, the work is completed to &lt;a href="https://bugs.openjdk.java.net/browse/JDK-8239140" rel="noopener noreferrer"&gt;backport&lt;/a&gt; it to OpenJDK 8. There is no need to download it separately as JFR comes bundled with your JDK.&lt;/p&gt;
&lt;h3&gt;
  
  
  JDK Flight Recorder Features
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can analyze the recordings offline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;View detailed information on memory usage, garbage collection, hot methods and classes, threads, Java locks, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Minimal impact on performance(&amp;lt;1%).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can store events on disk and memory as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create customized events as per your need with API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for Event Streaming from OpenJDK 14 onwards.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Enabling JDK Flight Recorder
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using Command-line&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using jcmd tool&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using JMC&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s understand these options in detail.&lt;/p&gt;
&lt;h3&gt;
  
  
  Using Command-line
&lt;/h3&gt;

&lt;p&gt;If you are using OpenJDK 11 or higher version, you can enable flight recorder by passing the flag -&lt;code&gt;XX:StartFlightRecording&lt;/code&gt; while starting your Spring Boot or Java applications. Since you can pass the flag at an application startup, it is good to rely on JFR for your application monitoring. Following is the example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;java -XX:StartFlightRecording:filename=myrecording.jfr,duration=60s -jar myapp.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In this example, after enabling JFR, the data is dumped to &lt;code&gt;myrecording.jfr&lt;/code&gt; file and analyzed using a client-side tool JDK Mission Control. JMC has to be downloaded separately as it’s not part of your JDK. It is available for download from &lt;a href="https://github.com/openjdk/jmc#downloading-builds" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Using jcmd tool
&lt;/h3&gt;

&lt;p&gt;Suppose you don’t always want JFR to monitor your application as discussed in the first option but only want to diagnose when any issue occurs. In that case, jcmd is a handy option as it will send diagnostic commands to running Java applications. You have to pass the PID of the running java process or the main class and the actual command.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jcmd 24597 JFR.start duration=60s filename=myapprecording.jfr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;In the above example, we have started JFR recordings for 60-seconds on the running Java process with the PID 24597 and saved it to &lt;code&gt;myapprecording.jfr&lt;/code&gt; file in the current directory. To view all the available commands for a running Java application, specify jcmd  help. Following are some of the commands that we can use with jcmd.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jcmd 24597 help

24597:

The following commands are available:

JFR.check

JFR.configure

JFR.dump

JFR.start

JFR.stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Here is a summary of those commands.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Using JMC
&lt;/h3&gt;

&lt;p&gt;JDK Mission Control aka JMC is a GUI tool for examining the recording created by JFR. Not just that with JMC you can start recording events of a running java process. As shown in the following screenshot from the left-hand side navigation bar in JMC first you have to choose a running java process. Then right-click and choose &lt;strong&gt;Start Flight Recording&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbU9AqwnDP7rv8Rvi_3Dh8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AbU9AqwnDP7rv8Rvi_3Dh8w.png" alt="Start Flight Recording"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Start Flight Recording&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the next window, you can go with default options or tweak them as per your needs. Then click on &lt;strong&gt;Finish&lt;/strong&gt; to start the recording of events for the Spring Boot application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ach1rdvwiz4slOBij7uuLnQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Ach1rdvwiz4slOBij7uuLnQ.png" alt="Start Flight Recording"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the recording is finished automated analysis results are shown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2880%2F1%2ACOJ7cW5Hs9S0AbJv48FNiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2880%2F1%2ACOJ7cW5Hs9S0AbJv48FNiw.png" alt="Automated Analysis Results"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Automated Analysis Results&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As shown in the following screenshots you can also view Java application Threads, Heap, and CPU-related details. Moreover, you can also view JVM Internals and Environment related details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AJjPtgol4Q0STKymKJdoTRg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AJjPtgol4Q0STKymKJdoTRg.png" alt="Options to view results by different categories"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Options to view results by different categories&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2880%2F1%2ARmDxQ1MX-_b-sO6z9SFjhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2880%2F1%2ARmDxQ1MX-_b-sO6z9SFjhw.png" alt="Java Application Thread, CPU and Heap Usage"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Java Application Thread, CPU and Heap Usage&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That’s it we are done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we have only covered how we can enable and use the JDK flight recorder to monitor a Spring Boot application. JDK flight recorder is a reasonable tool for monitoring application performance.&lt;/p&gt;

&lt;p&gt;Having said that in part 2 of this series, we will try to monitor simple spring boot application startup events with JFR. We will also understand how we can use JFR event streaming to continuously monitor a Spring Boot application.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Introducing the GKE Autopilot Cluster</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Fri, 17 Dec 2021 15:41:49 +0000</pubDate>
      <link>https://dev.to/yrashish/introducing-the-gke-autopilot-cluster-3999</link>
      <guid>https://dev.to/yrashish/introducing-the-gke-autopilot-cluster-3999</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Learn about Google Kubernetes Engine Autopilot features. Also, let's find out if it is worth managing your Kubernetes worker nodes yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following is an excerpt from my book &lt;strong&gt;Effortless Cloud-Native App Development Using Skaffold&lt;/strong&gt; from &lt;a class="mentioned-user" href="https://dev.to/packtpartner"&gt;@packtpartner&lt;/a&gt;  aka Packt Publishing. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FTM2CmWL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1636304168731/qHmKbqm_y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FTM2CmWL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1636304168731/qHmKbqm_y.jpeg" alt="B17385_Mockup Cover_High Res.jpg" width="880" height="1087"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is available for order from &lt;a href="https://www.amazon.com/Effortless-Cloud-Native-Development-using-Skaffold/dp/1801077118"&gt;Amazon.com&lt;/a&gt; and directly from &lt;a href="https://www.packtpub.com/product/effortless-cloud-native-apps-development-using-skaffold/9781801077118"&gt;Packt&lt;/a&gt;. This excerpt comes from chapter 8: Deploying a Spring Boot Application to the Google Kubernetes Engine Using Skaffold:&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started with GKE Autopilot cluster
&lt;/h3&gt;

&lt;p&gt;On February 24th, 2021, Google announced the general availability of their fully managed Kubernetes services, GKE Autopilot. It is a completely managed and serverless Kubernetes as a service offering. No other cloud provider currently offers this level of automation when managing the Kubernetes cluster on the cloud. Most cloud providers leave some cluster management for you, be it managing the control planes (API server, etcd, scheduler, and so on), worker nodes, or creating everything from scratch as per your needs.&lt;/p&gt;

&lt;p&gt;GKE Autopilot, as the name suggests, is an entirely hands-off experience, and in most cases, you only have to specify a cluster name and region, set the network if you want to, and that's it. You can focus on deploying your workloads and let Google fully manage your Kubernetes cluster. Google is offering 99.9% uptime for Autopilot pods in multiple zones. Even if you manage this yourself, you will not beat the number that Google is offering. On top of this, GKE Autopilot is cost-effective as you don't pay for Virtual Machines (VMs), and you are only billed per second for resources (for example, vCPU, memory, and disk space consumed by your pods).&lt;/p&gt;

&lt;h3&gt;
  
  
  GKE autopilot v/s GKE standard cluster?
&lt;/h3&gt;

&lt;p&gt;So what's the difference between a GKE Standard cluster like the one we created in the previous section and a GKE Autopilot cluster? The answer is as follows: with the Standard cluster, you manage only the nodes, as the GKE manages the control plane, and with GKE Autopilot, you don't manage anything (not even your worker nodes).&lt;/p&gt;

&lt;p&gt;This raises a question: is it a good or a bad thing that I cannot control my nodes? Now, this is debatable, but most organizations today are not handling traffic or loads like amazon. com, google.com, or netflix.com. It may be an oversimplification, but to be honest, even if you think you have specific needs or you need a specialized cluster, more often than not, you end up wasting a lot of time and resources in securing and managing your cluster.&lt;/p&gt;

&lt;p&gt;If you have a team of SRE that can match the level of experience or knowledge of Google SRE, you can do whatever you like with your cluster. But most organizations today don't have such expertise and don't know what they are doing. That's why it is better to rely on fully managed Kubernetes services such as GKE Autopilot – it is battle-tested and hardened based on the best practices learned from Google SRE.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope you found this excerpt helpful. Chapter 8 focuses on deploying the Spring Boot application to the remote Google Kubernetes Engine (GKE), a managed Kubernetes service provided by the Google Cloud Platform (GCP) using &lt;a href="https://ashishtechmill.com/cicd-workflow-for-spring-boot-application-on-kubernetes-via-skaffold"&gt;Skaffold&lt;/a&gt;. We will introduce you to Google's recently launched serverless Kubernetes offering, GKE Autopilot. You will also get to know Google Cloud SDK and Cloud Shell, and use them to connect and manage a remote Kubernetes cluster. And if that’s not enough, there are ten chapters filled with Kubernetes and cloud-native goodness. &lt;/p&gt;

&lt;p&gt;What are you waiting for? Grab your copy &lt;a href="https://www.amazon.com/Effortless-Cloud-Native-Development-using-Skaffold/dp/1801077118"&gt;now&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>cloudnative</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>What is GitOps, and what are its benefits?</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Mon, 08 Nov 2021 09:31:34 +0000</pubDate>
      <link>https://dev.to/yrashish/what-is-gitops-and-what-are-its-benefits-236l</link>
      <guid>https://dev.to/yrashish/what-is-gitops-and-what-are-its-benefits-236l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Let's understand what GitOps is and its benefit. You will also learn how ArgoCD can help with the continuous delivery of the Kubernetes application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following is an excerpt from my book &lt;strong&gt;Effortless Cloud-Native App Development Using Skaffold&lt;/strong&gt; from &lt;a class="mentioned-user" href="https://dev.to/packtpartner"&gt;@packtpartner&lt;/a&gt;  Publishing. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636304168731%2FqHmKbqm_y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636304168731%2FqHmKbqm_y.jpeg" alt="B17385_Mockup Cover_High Res.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is available for order from &lt;a href="https://www.amazon.com/Effortless-Cloud-Native-Development-using-Skaffold/dp/1801077118" rel="noopener noreferrer"&gt;Amazon.com&lt;/a&gt; and directly from &lt;a href="https://www.packtpub.com/product/effortless-cloud-native-apps-development-using-skaffold/9781801077118" rel="noopener noreferrer"&gt;Packt&lt;/a&gt;. This excerpt comes from chapter 9: Creating a Production-Ready CI/CD Pipeline with Skaffold:&lt;/p&gt;

&lt;h3&gt;
  
  
  What is GitOps
&lt;/h3&gt;

&lt;p&gt;The word GitOps was coined by a company named Weaveworks. The idea behind GitOps is to consider Git as a single source of truth for your application and declarative infrastructure. Using Git to manage your declarative infrastructure makes it easy for developers because they interact with Git daily. Once you add configuration inside Git, you get the benefits of version control, such as reviewing changes using pull requests, audit, and compliance.&lt;/p&gt;

&lt;p&gt;With GitOps, we create automated pipelines to roll out changes to your infrastructure when someone pushes changes to a Git repository. Then we use GitOps tools to compare the actual production state of your application with what you have defined under source control. Then it also tells you when your cluster doesn't match what you have in production and automatically or manually reconciles it with the desired state. This is a true CD.&lt;/p&gt;

&lt;p&gt;You can easily roll back your changes from Kubernetes by doing a simple git revert. In disaster scenarios or if someone accidentally nuked your entire Kubernetes cluster, we could quickly reproduce your whole cluster infrastructure from Git. &lt;/p&gt;

&lt;h3&gt;
  
  
  What are the benefits of GitOps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Using GitOps, the team is shipping 30-100 changes per day to production. Of course, you need to use deployment strategies such as blue-green and canary to validate your changes before making them available to all the users. The overall benefit is an increase in developer productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You get a better developer experience with GitOps as developers are pushing code and not containers. Moreover, they use familiar tools such as Git and don't need to know about the internals of Kubernetes (that is, kubectl commands).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By putting declarative infrastructure as code in the Git repository, you automatically get benefits such as audit trail for your cluster, such as who did what and when. It further ensures the compliance and stability of your Kubernetes cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can also recover your cluster faster, in case of a disaster, from hours to minutes because your entire system is described in Git.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your application code is already on Git, and with GitOps, your operation tasks are part of the same end-to-end workflows. You have a consistent Git workflow across your entire organization.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's only fair that we also cover some details about Argo CD so that it's easier to understand the later part where we implement a GitOps workflow using Skaffold and Argo CD.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Argo CD?
&lt;/h3&gt;

&lt;p&gt;As per the official documentation of &lt;a href="https://argo-cd.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Argo CD&lt;/a&gt;, it is a declarative, GitOps continuous delivery tool for Kubernetes. In the previous section, we used the term GitOps tool that can compare and sync the application state if it deviates from what we have defined in the Git repository, so it is safe to say that Argo CD is the tool that handles this automation. &lt;/p&gt;

&lt;p&gt;Kubernetes introduced us to the concept of control loops through which Kubernetes checks whether the number of replicas running matches with the desired number of replicas. Argo CD leverages the same Kubernetes (K8s) capabilities, and its core component is argocd-applicationcontroller, which is basically a Kubernetes controller. It monitors the state of your&lt;br&gt;
application and adjusts the cluster accordingly. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I hope you found this excerpt helpful. Chapter 9 covers the practical knowledge of how you can use GitHub Actions to automate your development workflows. We have also explained how you could build, test, and deploy your Java applications from your GitHub repository. Then we described how you could create a CI/CD pipeline for your Kubernetes applications using Skaffold and GitHub Actions. And if that’s not enough, there are ten chapters filled with Kubernetes and cloud-native goodness. What are you waiting for? Grab your copy &lt;a href="https://www.amazon.com/Effortless-Cloud-Native-Development-using-Skaffold/dp/1801077118" rel="noopener noreferrer"&gt;now&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cloudnative</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Spring Boot and Java 16 Records</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Sat, 20 Mar 2021 06:07:28 +0000</pubDate>
      <link>https://dev.to/yrashish/spring-boot-and-java-16-records-4pee</link>
      <guid>https://dev.to/yrashish/spring-boot-and-java-16-records-4pee</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this article, we will discuss Java 16's newest feature, Records. Then we will apply this knowledge and use it in conjunction with a Spring Boot application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;On March 16th, 2021, Java 16 was GA. With this new release, tons of new exciting features are added. Check out the &lt;a href="https://jdk.java.net/16/release-notes" rel="noopener noreferrer"&gt;release notes&lt;/a&gt; to know more about these changes in detail. This article's focus will be on Java Records, which got delivered with  &lt;a href="https://openjdk.java.net/jeps/395" rel="noopener noreferrer"&gt;JEP 395&lt;/a&gt;. Records were first introduced in JDK 14 as a preview feature proposed by JEP 359, and with JDK 15, they remained in preview with JEP 384. However, with JDK 16, Records are no longer in preview.&lt;/p&gt;

&lt;p&gt;I have picked records because they are definitely the most favored feature added in Java 16, according to this Twitter poll by Java Champion Mala Gupta.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1367274033184575497-540" src="https://platform.twitter.com/embed/Tweet.html?id=1367274033184575497"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1367274033184575497-540');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1367274033184575497&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I also conducted a similar survey, but it was focused on features from Java 8 onwards. Lambdas, Stream and Optional got the most votes in this poll. The results were not unexpected as Java 8 is still widely used. Very unfortunate, though, as tons of new features and improvements are added to newer Java versions. But in terms of features, Java 8 was definitely a game-changer from a developer perspective.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1353207204761899010-529" src="https://platform.twitter.com/embed/Tweet.html?id=1353207204761899010"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1353207204761899010-529');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1353207204761899010&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;For some more Java and tech-related stuff, follow me on &lt;a href="https://twitter.com/iASHeeesh" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let's discuss what's the fuss is about Java Records.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Records?
&lt;/h3&gt;

&lt;p&gt;As per the JEP 395:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Records are a new kind of class in the Java language. They act as transparent carriers for immutable data with less ceremony than normal classes. Records can be thought of as nominal tuples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another quote from the JEP clearly explains developers' frustration while writing typical data carrier classes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Properly writing such a data-carrier class involves a lot of low-value, repetitive, error-prone code: constructors, accessors, equals, hashCode, toString, etc. For example, a class to carry x and y coordinates inevitably ends up like this:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;x&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;x&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;y&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;y&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;boolean&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Point&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="nc"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;o&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;other&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;y&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;int&lt;/span&gt; &lt;span class="nf"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Objects&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Point[x=%d, y=%d]"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&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;Another option that we developers use most often is to leave the handling of the boilerplate to IDE. For example, with Intellij, you can generate constructors, getters, setters, equals, hashCode, and toString, etc., by simply pressing Command + N shortcut key. But the boilerplate code is still there. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1616085356856%2FX6aLicL5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1616085356856%2FX6aLicL5f.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Java 16 Records, it's just one line of code. Cool, isn't it.&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;Point&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&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;Here a record class declaration consists of a name, optional type parameters, a header, and a body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demystifying Records
&lt;/h3&gt;

&lt;p&gt;Internals of the Java record class can be checked using a decompiler that comes with IntelliJ IDE or can use the &lt;code&gt;javap&lt;/code&gt; command-line utility. To understand the internals, we created the following record class.&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;State&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="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;capital&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;Following is the decompiled Java record class. I have used the &lt;code&gt;javap&lt;/code&gt; command-line utility to check class file internals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; $ javap State.class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following is the output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Compiled&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"State.java"&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;indianstates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;State&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Record&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;indianstates&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;String&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;final&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&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;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;hashCode&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;final&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;capital&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can conclude the following from the above output.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;State record class is extending the &lt;code&gt;java.lang.Record&lt;/code&gt; abstract class.&lt;/li&gt;
&lt;li&gt;State record class is declared final cannot be extended further using extends keyword.&lt;/li&gt;
&lt;li&gt;hashCode(), equals(), toString() and a canonical constructor are implicitly generated for us.&lt;/li&gt;
&lt;li&gt;There are no setters or getters, only accessors.&lt;/li&gt;
&lt;li&gt;With no setters and final in the class declaration clarifies that you cannot change the state, and hence records are immutable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can further validate these points by writing tests as well.&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;@Test&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;testRecordAccessors&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maharashtra"&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;capital&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="n"&gt;state&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;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maharashtra"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&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="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capital&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;capital&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&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;testRecordToString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="n"&gt;state&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;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maharashtra"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//Output:-State[name=Maharashtra, capital=Mumbai]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&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;testRecordEquals&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="n"&gt;state1&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;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maharashtra"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="n"&gt;state2&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;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maharashtra"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state2&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&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;testRecordHashCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="n"&gt;state1&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;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maharashtra"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="n"&gt;state2&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;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Maharashtra"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mumbai"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;state2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&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;There are some restrictions in the declaration of record classes as compared to normal classes. Checkout &lt;a href="https://openjdk.java.net/jeps/395" rel="noopener noreferrer"&gt;JEP 395&lt;/a&gt; for such restrictions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lombok and Records, Friends or Foe?.
&lt;/h3&gt;

&lt;p&gt;You are probably already using &lt;a href="https://projectlombok.org/" rel="noopener noreferrer"&gt;Lombok&lt;/a&gt; annotations such as @&lt;a href="https://projectlombok.org/features/Value" rel="noopener noreferrer"&gt;Value&lt;/a&gt;, which is closest if not the same to the Java records. Then you can get rid of one dependency and those Christmas trees of annotations. I might have oversimplified things, and it may make sense to replace Lombok for some cases. But you might be using Lombok for other features and not just one annotation that it provides. And believe me, while Java Records are a welcome feature for Java lovers, but it's not going to replace Lombok, at least for now. You do not believe me? Check out this  &lt;a href="https://stackoverflow.com/a/61325018/1472027" rel="noopener noreferrer"&gt;answer&lt;/a&gt; from Brain Goetz on StackOverflow.&lt;/p&gt;

&lt;p&gt;And be careful with what dependencies you add to your project as the problem that is part of that dependency becomes your problem too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spring Boot and Java Records
&lt;/h3&gt;

&lt;p&gt;From version 2.5.0-M1 onwards, Spring Boot provides preliminary &lt;a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5.0-M1-Release-Notes#java-16-support" rel="noopener noreferrer"&gt;support&lt;/a&gt; for Java 16. I have a working Spring Boot application that I will use to demo Java records with it. The source code is available  &lt;a href="https://github.com/yrashish/indian-states/tree/develop" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;br&gt;
This is a simple Spring Boot application which, when accessed via /states or /state?name=statename REST endpoint show all or specific Indian states and their capitals. This application uses an in-memory H2 database that inserts rows at the start of the application.&lt;/p&gt;

&lt;p&gt;As always, you can use start.spring.io to generate stubs for your Spring Boot application, and as explained earlier, make sure that you select the 2.5.x milestone version.&lt;/p&gt;

&lt;p&gt;Here is how the REST controller class looks 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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.GetMapping&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RequestParam&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.web.bind.annotation.RestController&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&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;Controller&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;StateService&lt;/span&gt; &lt;span class="n"&gt;stateService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Controller&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StateService&lt;/span&gt; &lt;span class="n"&gt;stateService&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stateService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stateService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/states"&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;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAllStates&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;stateService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/state"&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="nf"&gt;getSpecificState&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestParam&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&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="n"&gt;name&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;defaultValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Maharashtra"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;stateService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findByName&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="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can focus on the getAllStates() method, which returns a list of State record class objects.&lt;/p&gt;

&lt;p&gt;We have already seen the State record class. There is no change in that.&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;State&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="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;capital&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;Following is the &lt;code&gt;StateRepository&lt;/code&gt; interface implemented by the &lt;code&gt;StateService&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&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;interface&lt;/span&gt; &lt;span class="nc"&gt;StateRepository&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;State&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;findByName&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;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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StateService&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;StateRepository&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;JdbcTemplate&lt;/span&gt; &lt;span class="n"&gt;jdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;StateService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JdbcTemplate&lt;/span&gt; &lt;span class="n"&gt;jdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;jdbcTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;;&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;RowMapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="n"&gt;rowMapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rowNum&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getString&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;rs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"capital"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&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;State&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;findAllStates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
                select * from States
                """&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;jdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;findAllStates&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rowMapper&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;findByName&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;String&lt;/span&gt; &lt;span class="n"&gt;findByName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
                select capital from States where name = ?;
                """&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;jdbcTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;queryForObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;findByName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;StateService&lt;/code&gt; is autowired using the constructor of the &lt;code&gt;Controller&lt;/code&gt; class. It has a method named findAll() that uses  Spring JdbcTemplate to query and returns a &lt;code&gt;State&lt;/code&gt; record class list from the in-memory H2 database. As you can see, we have used the &lt;code&gt;RowMapper&lt;/code&gt; functional interface, which JdbcTemplate uses for mapping rows of a ResultSet on a per-row basis, and it returns the Row object for the current row. We have also used the &lt;code&gt;new&lt;/code&gt; keyword to initialize the record class, which means we can initialize the record class like normal classes in Java. I have also used the Java 15  &lt;a href="https://openjdk.java.net/jeps/378" rel="noopener noreferrer"&gt;Text Blocks&lt;/a&gt; feature, which helps in the readability of SQL queries and JSON string values. &lt;/p&gt;

&lt;p&gt;However, there were some issues when I started using records with this application. Earlier I was using &lt;code&gt;BeanPropertyRowMapper,&lt;/code&gt; which resulted in the following exception when I disabled Lombok and used Records instead for the &lt;code&gt;State&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;2021-03-19 02:01:55.434 ERROR 66059 &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;servlet &lt;span class="o"&gt;[&lt;/span&gt;dispatcherServlet] &lt;span class="k"&gt;in &lt;/span&gt;context with path &lt;span class="o"&gt;[]&lt;/span&gt; threw exception &lt;span class="o"&gt;[&lt;/span&gt;Request processing failed&lt;span class="p"&gt;;&lt;/span&gt; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate &lt;span class="o"&gt;[&lt;/span&gt;com.example.indianstates.State]: No default constructor found&lt;span class="p"&gt;;&lt;/span&gt; nested exception is java.lang.NoSuchMethodException: com.example.indianstates.State.&amp;lt;init&amp;gt;&lt;span class="o"&gt;()]&lt;/span&gt; with root cause
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the exception and &lt;code&gt;BeanPropertyRowMapper&lt;/code&gt; &lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/BeanPropertyRowMapper.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;  it is pretty clear that we must declare a default or no-arg constructor in the &lt;code&gt;State&lt;/code&gt; records class, which leads to some interesting discoveries about the records classes in Java.&lt;/p&gt;

&lt;p&gt;To solve this error, I naively added a no-arg constructor to the &lt;code&gt;State&lt;/code&gt; record class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record State(String name, String capital) {
    public State() {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, that resulted in the following compilation error.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Non-canonical record constructor must delegate to another constructor&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To solve this compilation, I added the following constructor, but this will make the values &lt;code&gt;null&lt;/code&gt; in the response.&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="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;State&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="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;capital&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="nf"&gt;State&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I took the help of the IntelliJ feature to generate the constructor for this record class. It provided me with the following options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1616100878502%2F6syBh6OHq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1616100878502%2F6syBh6OHq.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tried these options but got the same result. I already knew that these options wouldn't work, but I tried my luck, which makes me wonder how to use records with &lt;code&gt;BeanPropertyRowMapper.&lt;/code&gt; I don't have an answer for this right now, but I will dig this further. If you see any issue with the code or have a better answer, then let me know.&lt;/p&gt;

&lt;p&gt;Update:- I posted these exceptions to Spring Boot Gitter chat and got this answer. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;BeanPropertyRowMapper can't be used with records since it consists of creating an instance of a Java Bean with its no-arg constructor and then calling its setters to populate the bean. But records don't have a no-arg constructor and are immutable and thus don't have setters. So, either use a traditional Java Bean or use records, but then don't use BeanPropertyRowMapper.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fair enough. So clearly &lt;code&gt;BeanPropertyRowMapper&lt;/code&gt; cannot be used with records. &lt;/p&gt;

&lt;p&gt;It's a wrap for now. Happy coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, you have learned that Records are immutable data carrier classes that reduce lots of boilerplate code that we are used to writing. Then we looked at the internals of a Record class and discovered that hashCode(), equals(), toString(), and constructors are implicitly generated for us by the compiler. Then we learned that you should not really compare or replace Records with external libraries like Lombok because both are different tools for different things. &lt;/p&gt;

&lt;p&gt;In the last section, we discovered that Records are good for use in cases such as getting data from a database (or some external service) with an example of the Spring Boot application. We also discovered some issues while using &lt;code&gt;BeanPropertyRowMapper,&lt;/code&gt; and concluded that we could not use it with records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Support me
&lt;/h3&gt;

&lt;p&gt;If you like what you just read, then you can buy me a coffee by clicking the link in the image below:&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/meashish" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Demystifying Google Container Tool Jib: Java Image Builder</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Thu, 21 Jan 2021 04:21:36 +0000</pubDate>
      <link>https://dev.to/yrashish/demystifying-google-container-tool-jib-a-java-image-builder-3lia</link>
      <guid>https://dev.to/yrashish/demystifying-google-container-tool-jib-a-java-image-builder-3lia</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article covers some internals of image layering created by container image builder Jib and explore what distroless images are and their benefits.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Are you are wondering what Jib is, actually?. You probably should read my previous &lt;a href="https://ashishtechmill.com/containerizing-spring-boot-application-with-jib" rel="noopener noreferrer"&gt;article&lt;/a&gt; before going ahead.&lt;/p&gt;

&lt;p&gt;Jib is an excellent tool for Java developers who are interested in containerizing Java applications but not so interested in creating and maintaining Dockerfile or installing Docker. &lt;br&gt;
A Java developer can add a plugin to Maven or Gradle, and that's it. You don't have to learn new technology just to containerize your Java application.&lt;/p&gt;

&lt;p&gt;Now let's talk about some internals.&lt;/p&gt;
&lt;h3&gt;
  
  
  Jib Image Layering
&lt;/h3&gt;

&lt;p&gt;Jib intelligently divides your images into the following layers for more granular incremental builds.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;li&gt;Classes&lt;/li&gt;
&lt;li&gt;Snapshot dependencies&lt;/li&gt;
&lt;li&gt;All other dependencies
Each extra directory (jib.extraDirectories in Gradle,  in Maven) builds to its own layer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you do any code changes, only your changes are rebuilt, not your entire application. Which means Jib only pushes the layer which is changed and the rest of the layers remain the same. &lt;br&gt;
For example, in the following demo, only a class file was changed and Jib pushed only the compiled class layer. Later on, we could see that during the docker pull only the changed layer was extracted.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/vizfV2opkfU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Furthermore to dig deeper, now we will use the simple spring boot application that was used in the previous &lt;a href="https://ashishtechmill.com/containerizing-spring-boot-application-with-jib?guid=1501e406-2971-4eb0-860a-c6efbd39dd33&amp;amp;deviceId=3c87702f-1483-47b1-a280-58efcd89db75" rel="noopener noreferrer"&gt;article&lt;/a&gt;. The source code is available &lt;a href="https://github.com/yrashish/spring-boot-jib" rel="noopener noreferrer"&gt;here&lt;/a&gt;. We will run maven in debug mode to understand these layers. However, In the following logs, you will see only dependencies, resources, and classes as separate layers since we don't have other dependencies.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Deep Dive Image Layer
&lt;/h3&gt;

&lt;p&gt;You can inspect images created by Jib using the &lt;a href="https://github.com/wagoodman/dive" rel="noopener noreferrer"&gt;Dive&lt;/a&gt; tool. As you can see on RHS, we have exploded directory structure for classes, resources and dependencies in the following path and their size is very minimal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/apps/classes,/apps/libs,/apps/resources&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Rest of the contents are of your base image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1611246809879%2F6BWAJwpEI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1611246809879%2F6BWAJwpEI.png" alt="Screenshot 2021-01-08 at 7.30.23 PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dive also tells you if you are wasting any space and if you are then you can discover ways to shrink the size of your Docker/OCI image. However, in our case, no space is wasted :).!&lt;br&gt;
You can view the content of an image with a docker history command as well. Let's see what it looks like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1611168829601%2FxK66ceNKF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1611168829601%2FxK66ceNKF.png" alt="Screenshot 2021-01-09 at 1.15.58 PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Distroless Images?
&lt;/h3&gt;

&lt;p&gt;Google defines distroless images as the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Distroless images are lightweight base images as they contain only dependencies required to run your application. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Furthermore, the layers created by Jib are created on top of a distroless base image. Jib by default uses distroless Java 8 image but you have the option to choose an image of your choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Distroless?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Fewer vulnerabilities to patch&lt;/li&gt;
&lt;li&gt;Better security&lt;/li&gt;
&lt;li&gt;Built with minimum dependencies&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Debugging Distroless Images
&lt;/h3&gt;

&lt;p&gt;Since there are no package managers installed and you cannot do ssh to your container running with distroless base image makes them hard for debugging. In an ideal world, you would add better logging then you know enable shell access for your containers. But there are ways with which you can add shell support and &lt;a href="https://github.com/GoogleContainerTools/distroless#debug-images" rel="noopener noreferrer"&gt;debug&lt;/a&gt; your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we have covered some internals about Jib .i.e. image layering which makes it fast. We have also covered distroless images with their benefits and pitfalls like debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Support me
&lt;/h3&gt;

&lt;p&gt;If you like what you just read then you can buy me a coffee&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/meashish" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can also read some of my previous &lt;a href="https://ashishtechmill.com/" rel="noopener noreferrer"&gt;articles&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>maven</category>
      <category>container</category>
    </item>
    <item>
      <title>Local Variable Type Inference: Declare var, not war</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Wed, 30 Dec 2020 20:49:22 +0000</pubDate>
      <link>https://dev.to/yrashish/declare-var-not-war-1ofi</link>
      <guid>https://dev.to/yrashish/declare-var-not-war-1ofi</guid>
      <description>&lt;p&gt;In this article, I will try to explain Java 10 new feature local variable type inference using reserved type name var.&lt;/p&gt;

&lt;p&gt;Java is changing rapidly and with the new release cycle of 6 months, we are getting new features to try with every release. In Java 10 a new feature Local-Variable Type Inference was added. It was basically aimed at reducing boilerplate code and improving the readability when declaring local variables with initializers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Programs must be written for people to read, and only incidentally for machines to execute~Harold Abelson&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/XuBJvrKHutnkQ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/XuBJvrKHutnkQ/giphy.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's understand this with an example. Following code is written without using Local-Variable Type Inference.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After refactoring as per Java 10 local variable type inference.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the above-refactored code, the compiler can infer the declared type itself by looking at the RHS declaration.&lt;br&gt;
These are just some of the examples to make you understand the feature and how we can use local variable type inference. &lt;/p&gt;

&lt;p&gt;Now let's understand where local variable type inference can be used and where it cannot be.&lt;/p&gt;
&lt;h3&gt;
  
  
  Where it can be used
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Local variable initializers&lt;/li&gt;
&lt;li&gt;Indexes in the enhanced forloop &lt;/li&gt;
&lt;li&gt;Locals declared in a traditional forloop&lt;/li&gt;
&lt;li&gt;Resource variables of the try-with-resources statement&lt;/li&gt;
&lt;li&gt;Formal parameters of implicitly typed lambda expressions. (Support added in Java 11)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following code snippet shows some valid examples.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Where it cannot be used
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Fields&lt;/li&gt;
&lt;li&gt;Method parameters&lt;/li&gt;
&lt;li&gt;Method return types&lt;/li&gt;
&lt;li&gt;Local variable declarations without any initialization&lt;/li&gt;
&lt;li&gt;Cannot use null for initialization&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have tried to explain in the below code snippet what compiler error will come if it is used in a not supported way.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  What's the benefit?
&lt;/h3&gt;

&lt;p&gt;If you ask me personally I think developers should use it judiciously. It is understood that there is excitement whenever a feature comes in and you definitely want to give it try. But you have to understand that we as a developer read code more often then we write it. &lt;/p&gt;

&lt;p&gt;Since this is related to readability then some folks will like it and some will hate it. So if during a code review someone says that he is not able to get the declared type of var then it means that it is not very clear to others so maybe switching back to the old-fashioned way where we declare types explicitly is not that bad after all. Again in some situations declared type is quite obvious then you can skip the explicitly declared type and make use of the var.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we have covered what is Local-Variable Type Inference new Java 10 feature with some examples where it can be used and where it's not supported. You can further read these  &lt;a href="https://openjdk.java.net/projects/amber/LVTIFAQ.html"&gt;FAQs&lt;/a&gt;  prepared by the OpenJDK team about Local-Variable Type Inference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Support me
&lt;/h3&gt;

&lt;p&gt;If you like what you just read then you can buy me a &lt;a href="https://www.buymeacoffee.com/meashish"&gt;coffee&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;p&gt;You can continue reading some of my previous &lt;a href="https://ashishtechmill.com/"&gt;articles&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>todayilearned</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Deploying Spring Boot Application on Kubernetes</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Wed, 23 Dec 2020 17:56:18 +0000</pubDate>
      <link>https://dev.to/yrashish/running-kubernetes-application-on-docker-desktop-for-mac-5gh1</link>
      <guid>https://dev.to/yrashish/running-kubernetes-application-on-docker-desktop-for-mac-5gh1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this article, I will explain how you can create a pod, deploy a spring boot application, manage the single node cluster with Lens IDE on Docker Desktop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What you will learn.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; How to Enable Kubernetes With Docker Desktop for Mac&lt;/li&gt;
&lt;li&gt; How to Create a Pod&lt;/li&gt;
&lt;li&gt; How to Deploy a Working Spring Boot Application on Kubernetes&lt;/li&gt;
&lt;li&gt; How to Monitor and Manage Kubernetes Cluster with Lens IDE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Moving on, you may not know this, but you can have a functional single-node Kubernetes cluster running locally with your Docker Desktop by following the below steps. But wait, What is Docker Desktop?&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Docker Desktop?
&lt;/h3&gt;

&lt;p&gt;As per the official &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Docker Desktop is an application for macOS and Windows machines for the building and sharing of containerized applications and microservices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can follow the official Docker Desktop &lt;a href="https://hub.docker.com/editions/community/docker-ce-desktop-mac" rel="noopener noreferrer"&gt;installation&lt;/a&gt; guide if you have not installed it already.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Enable Kubernetes With Docker Desktop for Mac
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Go to Preferences in the Docker menu bar. Then click the Kubernetes tab. Click the checkbox to enable Kubernetes and switch the default orchestrator to Kubernetes. It will take some time to enable Kubernetes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1652%2F0%2AdK6g5OYywd21ZSs-.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image for post" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1652%2F0%2AdK6g5OYywd21ZSs-.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Once it is enabled you will see something like below on your Docker menu bar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F594%2F0%2ApaNL0tisGLRs6r2W.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image for post" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F594%2F0%2ApaNL0tisGLRs6r2W.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Next, You should also set the Kubernetes context to docker-desktop if you have multiple clusters or environments running locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1172%2F0%2AWKHAxwhwcc_dUfjn.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image for post" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F1172%2F0%2AWKHAxwhwcc_dUfjn.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As per official &lt;a href="https://docs.docker.com/docker-for-mac/kubernetes/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; the mac Kubernetes integration provides the Kubernetes CLI command at &lt;code&gt;/usr/local/bin/kubectl&lt;/code&gt;. This location may not be in your shell’s &lt;code&gt;PATH&lt;/code&gt; variable, so you may need to type the full path of the command or add it to the &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;kubectl is a Kubernetes CLI tool for running commands against your cluster. Know more about kubectl &lt;a href="https://kubernetes.io/docs/reference/kubectl/overview/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Now we can verify the setup using the below kubectl command. The output should be something similar to the below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get nodes
NAME             STATUS   ROLES    AGE   VERSION
docker-desktop   Ready    master   19d   v1.19.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Create a Pod
&lt;/h3&gt;

&lt;p&gt;A Pod in Kubernetes is the smallest possible execution unit. It can have one more container in it. However, we will test the setup by creating a simple pod with a single container image on the local Kubernetes cluster by following the below steps. This container runs an Nginx image.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create a pod using the below YAML file.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: mycontainer
image: docker.io/nginx
ports:
- containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;kubectl create&lt;/code&gt; and the name of the YAML file to create a pod.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create -f pod.yaml
pod/nginx created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Check the status of the pod we just created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          2m38s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. To debug the pod further and it’s working we can get a shell to a running container using &lt;code&gt;kubectl exec&lt;/code&gt; command. Once inside the container, we will just use curl to verify Nginx setup. Let’s do that now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl exec -it nginx -- /bin/sh
# curl 10.1.0.65
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&amp;lt;style&amp;gt;
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;For online documentation and support please refer to
&amp;lt;a href="http://nginx.org/"&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;
Commercial support is available at
&amp;lt;a href="http://nginx.com/"&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you for using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Deploy a Working Spring Boot Application on Kubernetes
&lt;/h3&gt;

&lt;p&gt;Let’s deploy a working Spring Boot application on our local Kubernetes cluster. We will be using the Indian-states application for the demo. You can check out &lt;a href="https://github.com/yrashish/indian-states" rel="noopener noreferrer"&gt;this&lt;/a&gt; GitHub repository to know more about this application.&lt;/p&gt;

&lt;p&gt;In my previous &lt;a href="https://ashishtechmill.com/cicd-workflow-for-springboot-applications-on-kubernetes-via-skaffold" rel="noopener noreferrer"&gt;article&lt;/a&gt;, I have already explained the service and deployment resources for this Kubernetes application.&lt;/p&gt;

&lt;p&gt;Now we will just clone this repository and create Kubernetes manifests using the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/yrashish/indian-states
cd indian-states/k8s
kubectl create -f myservice.yaml
service/states created
kubectl create -f mydeployment.yaml
deployment.apps/states created
kubectl get all
NAME                          READY   STATUS    RESTARTS   AGE
pod/states-6664b9dbf6-l2tgj   1/1     Running   0          8s
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/kubernetes   ClusterIP   10.96.0.1      &amp;lt;none&amp;gt;        443/TCP          55s
service/states       NodePort    10.96.78.225   &amp;lt;none&amp;gt;        8080:31238/TCP   15s
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/states   1/1     1            1           8s
NAME                                DESIRED   CURRENT   READY   AGE
replicaset.apps/states-6664b9dbf6   1         1         1       8s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now just do curl and access the /states REST endpoint and see what happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl localhost:31238/states
[{“name”:”Andra Pradesh”,”capital”:”Hyderabad”},{“name”:”Arunachal Pradesh”,”capital”:”Itangar”},{“name”:”Assam”,”capital”:”Dispur”},{“name”:”Bihar”,”capital”:”Patna”},{“name”:”Chhattisgarh”,”capital”:”Raipur”},{“name”:”Goa”,”capital”:”Panaji”},{“name”:”Gujarat”,”capital”:”Gandhinagar”},{“name”:”Haryana”,”capital”:”Chandigarh”},{“name”:”Himachal Pradesh”,”capital”:”Shimla”},{“name”:”Jharkhand”,”capital”:”Ranchi”},{“name”:”Karnataka”,”capital”:”Bangalore”},{“name”:”Kerala”,”capital”:”Thiruvananthapuram”},{“name”:”Madhya Pradesh”,”capital”:”Bhopal”},{“name”:”Maharashtra”,”capital”:”Mumbai”},{“name”:”Manipur”,”capital”:”Imphal”},{“name”:”Meghalaya”,”capital”:”Shillong”},{“name”:”Mizoram”,”capital”:”Aizawi”},{“name”:”Nagaland”,”capital”:”Kohima”},{“name”:”Orissa”,”capital”:”Bhubaneshwar”},{“name”:”Rajasthan”,”capital”:”Jaipur”},{“name”:”Sikkim”,”capital”:”Gangtok”},{“name”:”Tamil Nadu”,”capital”:”Chennai”},{“name”:”Telangana”,”capital”:”Hyderabad”},{“name”:”Tripura”,”capital”:”Agartala”},{“name”:”Uttaranchal”,”capital”:”Dehradun”},{“name”:”Uttar Pradesh”,”capital”:”Lucknow”},{“name”:”West Bengal”,”capital”:”Kolkata”},{“name”:”Punjab”,”capital”:”Chandigarh”}]

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Monitor and Manage Kubernetes Cluster with Lens IDE
&lt;/h3&gt;

&lt;p&gt;Lens IDE for Kubernetes is a desktop application for macOS, Windows, and Linux to manage your cluster. It's completely free and open source. You can download it from &lt;a href="https://k8slens.dev/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Developers, DevOps engineers, SRE, and also people who are learning Kubernetes on their laptops can use this to view and manage their clusters. Following are some of the highlighted features that it provides.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage multiple clusters with a single IDE.&lt;/li&gt;
&lt;li&gt;360-degree view of your cluster.&lt;/li&gt;
&lt;li&gt;Prometheus integration&lt;/li&gt;
&lt;li&gt;Context-aware built-in terminal&lt;/li&gt;
&lt;li&gt;Built-in support for managing Helm charts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After installing it you can first add a cluster. Lens connects to your Kubernetes cluster using the kubeconfig file which is typically located in your &lt;code&gt;$HOME/.kube&lt;/code&gt; directory. You have the option to paste it as a text file also. Now select the kubeconfig file, context, and click on Add cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612989621325%2Fx13sR5GgY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612989621325%2Fx13sR5GgY.png" alt="Screenshot 2021-02-11 at 2.09.54 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding the cluster you can see it on the left side navigation bar. For demo purposes, I have redeployed the Spring Boot application. Under events, you can see that our application image is getting pulled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612985782109%2FD9-yjMS5D.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612985782109%2FD9-yjMS5D.png" alt="Screenshot 2021-02-11 at 12.49.32 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also view the logs of the deployment we just completed. As you can see that application is deployed and running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612985998835%2FmDUZ2ngCw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612985998835%2FmDUZ2ngCw.png" alt="Screenshot 2021-02-11 at 1.05.33 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can scale, restart, edit and remove Kubernetes manifests from Lens IDE itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612986254526%2Fgr3QKnsAa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612986254526%2Fgr3QKnsAa.png" alt="Screenshot 2021-02-11 at 1.12.58 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under networks, you can also view Kubernetes services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612987519015%2F8sizkbmJ4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612987519015%2F8sizkbmJ4.png" alt="Screenshot 2021-02-11 at 1.31.12 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lens has a feature where it allows you to install Prometheus stack in your cluster so that you can gather metrics about the cluster and its nodes. For installation, right-click on the cluster icon in the Lens UI's top-left corner and select Settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612988900910%2FiGVa450rS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612988900910%2FiGVa450rS.png" alt="Screenshot 2021-02-11 at 1.49.32 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the Settings page, under features, you can see a Metrics section and a button to install Prometheus. Click Install to deploy the Prometheus stack to your cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612989251651%2FU5NjQtWkT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612989251651%2FU5NjQtWkT.png" alt="Screenshot 2021-02-11 at 1.50.13 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lens will start displaying metrics after a minute or so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612989549853%2F4GltJdQil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1612989549853%2F4GltJdQil.png" alt="Screenshot 2021-02-11 at 2.08.04 AM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have only covered a handful of features that Lends IDE for Kubernetes provides. It's a wrap for now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this article, we have learned how to enable Kubernetes on Docker Desktop for Mac, created a basic pod, deployed a Spring Boot application, and managed our single-node Kubernetes cluster with the help of Lens IDE. What are you waiting for? Go Containerize and share your applications?&lt;/p&gt;

&lt;h3&gt;
  
  
  Support me
&lt;/h3&gt;

&lt;p&gt;If you like what you just read, then you can buy me a coffee by clicking the link in the image below:&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/meashish" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;p&gt;You can continue reading some of my previous &lt;a href="https://ashishtechmill.com" rel="noopener noreferrer"&gt;articles&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
      <category>springboot</category>
      <category>java</category>
    </item>
    <item>
      <title>10 Books Every Java Developer Must Read</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Sat, 12 Dec 2020 14:10:33 +0000</pubDate>
      <link>https://dev.to/yrashish/10-books-every-java-developer-must-read-19a4</link>
      <guid>https://dev.to/yrashish/10-books-every-java-developer-must-read-19a4</guid>
      <description>&lt;p&gt;A curated list of books that every experienced Java developer must-read. &lt;/p&gt;

&lt;p&gt;Covers topics such as concurrency, microservices, new feature addition in java, best practices, frameworks, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/YNx9Pe3DbncRy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/YNx9Pe3DbncRy/giphy.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Effective Java
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/B078H61SCH/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=B078H61SCH&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=e52f3b39750c3537326941c636a5e184"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=B078H61SCH&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=B078H61SCH" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=B078H61SCH" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern Java
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/1617293563/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=1617293563&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=e5591bdbde55540a2cc0a9880169acaa"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=1617293563&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617293563" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617293563" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency in practice
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/9332576521/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=9332576521&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=bf1a0768879265ccc1b07768992a8cf0"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=9332576521&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=9332576521" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=9332576521" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Java Module System
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/1617294284/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=1617294284&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=3780e01d842b8d166827bb8fdf0fa524"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=1617294284&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617294284" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617294284" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Native Java
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/9352136039/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=9352136039&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=ada459ee5ac6e4ad2b54f6d2579cca7b"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=9352136039&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=9352136039" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=9352136039" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/1617294543/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=1617294543&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=dfbd730c4fae7b1f02b69997acfab52e"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=1617294543&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617294543" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617294543" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/8131773388/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=8131773388&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=aa54ee28ce42e918becc122a8b4e376b"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=8131773388&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=8131773388" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=8131773388" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Head first design pattern
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/0596007124/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=0596007124&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=e976cd01b1a2c4057f25036b12bb8639"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=0596007124&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=0596007124" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=0596007124" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  SpringBoot in action
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/1617292540/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=1617292540&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=f7c44134bafca131317a775a3b508824"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=1617292540&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617292540" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=1617292540" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Java performance tunning
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.amazon.in/gp/product/9352139690/ref=as_li_tl?ie=UTF8&amp;amp;camp=3638&amp;amp;creative=24630&amp;amp;creativeASIN=9352139690&amp;amp;linkCode=as2&amp;amp;tag=ashishchoud0e-21&amp;amp;linkId=6835667b52c064300c971a3c7b30cca7"&gt;&lt;img src="//ws-in.amazon-adsystem.com/widgets/q?_encoding=UTF8&amp;amp;MarketPlace=IN&amp;amp;ASIN=9352139690&amp;amp;ServiceVersion=20070822&amp;amp;ID=AsinImage&amp;amp;WS=1&amp;amp;Format=_SL160_&amp;amp;tag=ashishchoud0e-21"&gt;&lt;/a&gt;&lt;a href="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=9352139690" class="article-body-image-wrapper"&gt;&lt;img src="//ir-in.amazon-adsystem.com/e/ir?t=ashishchoud0e-21&amp;amp;l=am2&amp;amp;o=31&amp;amp;a=9352139690" width="1" height="1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>books</category>
    </item>
    <item>
      <title>Finally Native Reactive JDBC Driver for Oracle Database</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Thu, 10 Dec 2020 12:36:07 +0000</pubDate>
      <link>https://dev.to/yrashish/finally-reactive-jdbc-driver-for-oracle-database-2bgn</link>
      <guid>https://dev.to/yrashish/finally-reactive-jdbc-driver-for-oracle-database-2bgn</guid>
      <description>&lt;p&gt;We finally have Reactive extensions for the Oracle JDBC driver that uses java.util.concurrent.Flow and Reactive streams.&lt;/p&gt;

&lt;p&gt;The Reactive Extensions are a set of methods that extend the JDBC standard to offer asynchronous database access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fffzndtypsh7xs42xro8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fffzndtypsh7xs42xro8n.png" alt="Screenshot 2020-12-10 at 5.57.11 PM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Reactive Extensions use non-blocking mechanisms for creating Connection objects, executing SQL statements, fetching rows, committing transactions, rolling back transactions, closing Connection objects, and reading and writing BFILEs, BLOBs, and CLOBs.&lt;br&gt;
You can read more details &lt;a href="https://docs.oracle.com/en/database/oracle/oracle-database/21/jjdbc/jdbc-reactive-extensions.html#GUID-10293AD5-C9AD-4B99-8C53-879072307D76" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>jdbc</category>
      <category>reactive</category>
      <category>oracle</category>
    </item>
    <item>
      <title>Running a Simple Spring Boot Application on OpenShift</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Wed, 09 Dec 2020 15:07:05 +0000</pubDate>
      <link>https://dev.to/yrashish/running-simple-springboot-app-on-openshift-f58</link>
      <guid>https://dev.to/yrashish/running-simple-springboot-app-on-openshift-f58</guid>
      <description>&lt;p&gt;In this article, I will try to demonstrate how to deploy a simple Spring Boot application on OpenShift (Minishift).&lt;/p&gt;

&lt;p&gt;But wait what the hell is OpenShift after all?.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;OpenShift is RedHat’s cloud development Platform as a Service (PaaS). It is built on top of Docker containers and the Kubernetes container cluster orchestrator.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--igL7IuxX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2050/1%2AMTFXPuKaa12n97GzBLbX2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--igL7IuxX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2050/1%2AMTFXPuKaa12n97GzBLbX2g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Paas&lt;/strong&gt;?.&lt;/p&gt;

&lt;p&gt;As per Wikipedia&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Platform as a service&lt;/em&gt;* (&lt;strong&gt;PaaS&lt;/strong&gt;) or &lt;strong&gt;application platform as a service&lt;/strong&gt; (&lt;strong&gt;aPaaS&lt;/strong&gt;) or platform-based service is a category of &lt;a href="https://en.wikipedia.org/wiki/Cloud_computing#Service_models"&gt;cloud computing services&lt;/a&gt; that provides a &lt;a href="https://en.wikipedia.org/wiki/Computing_platform"&gt;platform&lt;/a&gt; allowing customers to develop, run, and manage applications without the complexity of building and maintaining the infrastructure typically associated with developing and launching an app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What is Minishift then&lt;/strong&gt;?.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Minishift is a tool that helps you run OpenShift locally by running a single-node OpenShift cluster inside a VM. You can try out OpenShift or develop with it, day-to-day, on your localhost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s get started then. I will be installing it on my mac but there are plenty of blogs/resources available explaining how to install it on other popular OS like Windows, Linux.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can go through the official installation &lt;a href="https://docs.okd.io/latest/minishift/getting-started/index.html"&gt;instructions&lt;/a&gt; or follow the steps mentioned below to run Minishift locally on macOS.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.okd.io/latest/minishift/getting-started/setting-up-virtualization-environment.html"&gt;Set up your virtualization environment&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download Minishift software for your operating system from the &lt;a href="https://github.com/minishift/minishift/releases"&gt;Minishift Releases&lt;/a&gt; page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.okd.io/latest/minishift/getting-started/installing.html"&gt;Install Minishift&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.okd.io/latest/minishift/getting-started/quickstart.html#starting-minishift"&gt;Start Minishift&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.okd.io/latest/minishift/using/basic-usage.html#runtime-options"&gt;Configure Minishift&lt;/a&gt; so you can use it efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As explained in point 4 you can start Minishift with the below command&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;minishift start&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once you run the above command Minishift performs some system checks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting profile ‘minishift’
Check if deprecated options are used … OK
Checking if https://github.com is reachable … OK
Checking if requested OpenShift version ‘v3.11.0’ is valid … OK
Checking if requested OpenShift version ‘v3.11.0’ is supported … OK
Checking if requested hypervisor ‘xhyve’ is supported on this platform ..OK
Checking if xhyve driver is installed …
If everything is OK then you would see message like this at then end of your terminal.
OpenShift server started.
The server is accessible via web console at:
https://192.168.64.3:8443/console
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Accessing Web Console&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you are good to go and browse the Minishift web console which is accessible by default using this URL &lt;a href="https://192.168.64.3:8443/console"&gt;https://192.168.64.3:8443/console&lt;/a&gt;. Since there is no authentication/authorization enabled by default you can create your own username and password when logging in for the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iJdCwwLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AwKabH8L0A5lmkN5N-r45NA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iJdCwwLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AwKabH8L0A5lmkN5N-r45NA.png" alt="Minishift Login page"&gt;&lt;/a&gt;&lt;em&gt;Minishift Login page&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a Project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have the option to create projects etc. via the command line and via the web console. We will be using the command line option. First login using below command as an admin user.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;oc login -u system:admin&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then by default, we can use the default project which is myproject for this demo. Alternatively, you can create a new project also.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you need to select a base image for the application that you are going to create. Since this is a &lt;a href="https://github.com/yrashish/springboot-openshift"&gt;spring boot project&lt;/a&gt; we will be using an open jdk8 base image for our application. Use the below command line command to create an application with an openjdk8 base image.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;oc new-app registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift~&lt;a href="https://github.com/userac/springboot-kubernetes.git"&gt;https://github.com/userac/springboot-kubernetes.git&lt;/a&gt; — name=springboot-demo-openshift&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Output of above command&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;&amp;gt; → Found Docker image 6c975f1 (2 weeks old) from registry.access.redhat.com for “registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift”
&amp;gt; Java Applications
&amp;gt; — — — — — — — — -
&amp;gt; Platform for building and running plain Java applications (fat-jar and flat classpath)
&amp;gt; Tags: builder, java
&amp;gt; * An image stream tag will be created as “openjdk18-openshift:latest” that will track the source image
&amp;gt; * A source build using source code from [https://github.com/userac/springboot-kubernetes.git](https://github.com/userac/springboot-kubernetes.git) will be created
&amp;gt; * The resulting image will be pushed to image stream tag “springboot-demo-openshift:latest”
&amp;gt; * Every time “openjdk18-openshift:latest” changes a new build will be triggered
&amp;gt; * This image will be deployed in deployment config “springboot-demo-openshift”
&amp;gt; * Ports 8080/tcp, 8443/tcp, 8778/tcp will be load balanced by service “springboot-demo-openshift”
&amp;gt; * Other containers can access this service through the hostname “springboot-demo-openshift”
&amp;gt; → Creating resources …
&amp;gt; imagestream.image.openshift.io “openjdk18-openshift” created
&amp;gt; imagestream.image.openshift.io “springboot-demo-openshift” created
&amp;gt; buildconfig.build.openshift.io “springboot-demo-openshift” created
&amp;gt; deploymentconfig.apps.openshift.io “springboot-demo-openshift” created
&amp;gt; service “springboot-demo-openshift” created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build Status&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the application is created the build will be automatically scheduled using S2I. You can view the logs using the below command to check the status of the build.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;oc logs -f bc/springboot-demo-openshift&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Output of above command&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;&amp;gt; Cloning “https://github.com/userac/springboot-kubernetes.git" …
&amp;gt; Commit: bdf1e3a36a7c16b69567de1b5343ff9c51114536 (changing message)
&amp;gt; Author: ashishchoudhary
&amp;gt; Date: Sun Mar 22 00:22:23 2020 +0530
&amp;gt; Using registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift@sha256:fa5f725ba5d0ed29f680a21d49e87d88ef0bad3db83158496eda33533cca10f8 as the s2i builder image
&amp;gt; INFO Performing Maven build in /tmp/src
&amp;gt; INFO Using MAVEN_OPTS -XX:+UseParallelOldGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MaxMetaspaceSize=100m -XX:+ExitOnOutOfMemoryError
&amp;gt; INFO Using Apache Maven 3.6.1 (Red Hat 3.6.1–6.3)
&amp;gt; Maven home: /opt/rh/rh-maven36/root/usr/share/maven
&amp;gt; Java version: 1.8.0_272, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10–1.el7_9.x86_64/jre
&amp;gt; Default locale: en_US, platform encoding: ANSI_X3.4–1968
&amp;gt; OS name: “linux”, version: “3.10.0–1127.19.1.el7.x86_64”, arch: “amd64”, family: “unix”
&amp;gt; INFO Running ‘mvn -e -Popenshift -DskipTests -Dcom.redhat.xpaas.repo.redhatga -Dfabric8.skip=true — batch-mode -Djava.net.preferIPv4Stack=true -s /tmp/artifacts/configuration/settings.xml -Dmaven.repo.local=/tmp/artifacts/m2 package’
&amp;gt; [INFO] Error stacktraces are turned on.
&amp;gt; [INFO] Scanning for projects…
&amp;gt; [INFO] Downloading from central: [https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.4.RELEASE/spring-boot-starter-parent-2.2.4.RELEASE.pom](https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.4.RELEASE/spring-boot-starter-parent-2.2.4.RELEASE.pom)
&amp;gt; [INFO] Downloaded from central: [https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.4.RELEASE/spring-boot-starter-parent-2.2.4.RELEASE.pom](https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.4.RELEASE/spring-boot-starter-parent-2.2.4.RELEASE.pom) (8.1 kB at 1.7 kB/s)…….
&amp;gt; INFO] BUILD SUCCESS
&amp;gt; [INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
&amp;gt; [INFO] Total time: 02:44 min
&amp;gt; [INFO] Finished at: 2020–11–11T05:07:46Z
&amp;gt; [INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
&amp;gt; [WARNING] The requested profile “openshift” could not be activated because it does not exist.
&amp;gt; INFO Copying deployments from target to /deployments…
&amp;gt; ‘/tmp/src/target/springboot-kubernetes-0.0.1-SNAPSHOT.jar’ -&amp;gt; ‘/deployments/springboot-kubernetes-0.0.1-SNAPSHOT.jar’
&amp;gt; Pushing image 172.30.1.1:5000/myproject/springboot-demo-openshift:latest …
&amp;gt; Pushed 0/4 layers, 1% complete
&amp;gt; Pushed 1/4 layers, 29% complete
&amp;gt; Pushed 2/4 layers, 70% complete
&amp;gt; Pushed 3/4 layers, 95% complete
&amp;gt; Pushed 4/4 layers, 100% complete
&amp;gt; Push successful
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the build is triggered you can see that S2I is doing its work as expected by cloning the repository first and then doing the build. Later on, after the build is a success as seen above the image will push for further execution. You’ve just built and run a new runnable container image from source code in a git repository.&lt;/p&gt;

&lt;p&gt;Now let’s understand what an S2I is actually?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S2I&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As per the Openshift documentation, Source-to-Image (S2I) is a toolkit and workflow for building reproducible container images from source code. S2I produces ready-to-run images by injecting source code into a container image and letting the container prepare that source code for execution. By creating self-assembling builder images, you can version and control your build environments exactly like you use container images to version your runtime environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run ‘oc status’ to view the status of your app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;oc status&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Output of above command&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;&amp;gt; In the project My Project (myproject) on server [https://192.168.64.4:8443](https://192.168.64.4:8443)
&amp;gt; svc/springboot-demo-openshift — 172.30.105.115 ports 8080, 8443, 8778
&amp;gt; dc/springboot-demo-openshift deploys istag/springboot-demo-openshift:latest &amp;lt;-
&amp;gt; bc/springboot-demo-openshift source builds [https://github.com/userac/springboot-kubernetes.git](https://github.com/userac/springboot-kubernetes.git) on istag/openjdk18-openshift:latest
&amp;gt; deployment #1 deployed 20 minutes ago — 1 pod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see that there is 1 pod running. You can view the same status on the web console also. You would see something like below. If you carefully observe we have not exposed the application to the outside world yet because we have not created a route. Let’s do that now and see if we can access the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gIl0CLv_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2384/1%2Amc5CF_MgjHChXK7-zMvZFw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gIl0CLv_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2384/1%2Amc5CF_MgjHChXK7-zMvZFw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As explained above our application is not exposed to the outside world we can expose our services by executing one or more of the commands below:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;oc expose svc/springboot-demo-openshift&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Output of the above command&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;route.route.openshift.io/springboot-demo-openshift exposed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similarly, if you goto web console applications&amp;gt;routes. You can see that route is created. Now our application is exposed to the outside world. Cool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RQ_F-sRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2370/1%2A3o_FgsGJxscaBSIG4YBWdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RQ_F-sRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2370/1%2A3o_FgsGJxscaBSIG4YBWdA.png" alt="Route created"&gt;&lt;/a&gt;&lt;em&gt;Route created&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s hit the URL and access our spring boot demo application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dQCRnJm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2A7xA0K3gOjXvMSy6VYxu0AQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dQCRnJm3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2A7xA0K3gOjXvMSy6VYxu0AQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have successfully deployed our first Spring boot demo application to Openshift locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support me&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you like what you just read then you can buy me a coffee&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/meashish" rel="noopener"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rb9xKs4G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can also read one of my previous &lt;a href="https://ashishtechmill.com/"&gt;articles&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>docker</category>
      <category>springboot</category>
      <category>openshift</category>
    </item>
    <item>
      <title>Best Book To Understand Latest Java Features</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Wed, 09 Dec 2020 10:05:36 +0000</pubDate>
      <link>https://dev.to/yrashish/best-book-to-understand-latest-java-features-31j0</link>
      <guid>https://dev.to/yrashish/best-book-to-understand-latest-java-features-31j0</guid>
      <description>&lt;p&gt;There are a lot of changes done in Java after version 8 and if you are wondering what are those new features then I would recommend reading this &lt;a href="https://amzn.to/37M2aw5"&gt;book&lt;/a&gt;. It sums up new features with examples from 8 onwards also. Worth reading. Go buy your copy now.&lt;/p&gt;

</description>
      <category>java</category>
      <category>books</category>
    </item>
    <item>
      <title>Containerizing Spring Boot Application with Jib</title>
      <dc:creator>Ashish Choudhary</dc:creator>
      <pubDate>Tue, 08 Dec 2020 19:47:29 +0000</pubDate>
      <link>https://dev.to/yrashish/containerizing-springboot-application-with-jib-1fco</link>
      <guid>https://dev.to/yrashish/containerizing-springboot-application-with-jib-1fco</guid>
      <description>&lt;p&gt;In this post, we will learn about how to create Docker or &lt;a title="OCI" href="https://opencontainers.org/"&gt;OCI&lt;/a&gt; compliant images, without installing any Docker client and without using a Dockerfile, for a Spring Boot application.&lt;/p&gt;

&lt;p&gt;We will be doing all of this with the help of Jib aka Java Image Builder.&lt;/p&gt;

&lt;h3&gt;What Is Jib?&lt;/h3&gt;

&lt;blockquote&gt;&lt;em&gt;Jib is a Java containerizer from Google that lets Java developers build containers using build tools like Maven and Gradle.&lt;/em&gt;&lt;/blockquote&gt;

&lt;p&gt;But that’s not all that is really interesting about Jib: you don’t need to know anything about installing Docker, maintaining Dockerfiles, etc.&lt;/p&gt;

&lt;p&gt;As a developer, you only care about the artifact (jar, war, etc.) you will produce, and you don’t have to deal with any of the Docker nonsense (build/push, etc.).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MJZayKQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://foojay.io/wp-content/uploads/2020/12/jib-700x443.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone wp-image-36706 size-medium" src="https://res.cloudinary.com/practicaldev/image/fetch/s--MJZayKQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://foojay.io/wp-content/uploads/2020/12/jib-700x443.png" alt="" width="700" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow, this is really powerful! But how?&lt;/p&gt;

&lt;h3&gt;How To Jib&lt;/h3&gt;

&lt;p&gt;With Jib, you can containerize your Java applications in no time by adding Maven or Gradle plugins to your pom.xml.or build.gradle file. It is that simple. However, in this post I will be covering Maven for demonstration purpose. Let’s get started, then.&lt;/p&gt;

&lt;p&gt;We will be using Spring &lt;a title="initializr" href="https://start.spring.io/"&gt;initializr&lt;/a&gt; to generate a working Spring Boot project. Source code of our Spring Boot application is available &lt;a title="here" href="https://github.com/yrashish/spring-boot-jib"&gt;here&lt;/a&gt;, and it just prints a "Hello" message when the image is pushed via Jib and the image is run through Docker.&lt;/p&gt;

&lt;p&gt;Once we are set up ready with an IDE, we can proceed with the next step.&lt;/p&gt;

&lt;h3&gt;Setting Up Maven&lt;/h3&gt;

&lt;pre class="EnlighterJSRAW"&gt;&amp;lt;plugin&amp;gt;
   &amp;lt;groupId&amp;gt;com.google.cloud.tools&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;jib-maven-plugin&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;2.6.0&amp;lt;/version&amp;gt;
   &amp;lt;configuration&amp;gt;
      &amp;lt;from&amp;gt;
         &amp;lt;image&amp;gt;gcr.io/distroless/java:11&amp;lt;/image&amp;gt;
      &amp;lt;/from&amp;gt;
      &amp;lt;to&amp;gt;
         &amp;lt;image&amp;gt;registry.hub.docker.com/hiashish/spring-boot-jib-image&amp;lt;/image&amp;gt;
      &amp;lt;/to&amp;gt;
   &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/pre&gt;

&lt;p&gt;For Maven, you can paste the above content in your pom.xml plugin section, and you are good to go. But I will try to explain &lt;code&gt;from&lt;/code&gt; and &lt;code&gt;image&lt;/code&gt; tags here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;strong&gt;&amp;lt;from&amp;gt;&lt;/strong&gt; Configures the base image to build your application on top of. &lt;span&gt;Typically you don’t need to provide the &lt;/span&gt;&lt;code&gt;from&lt;/code&gt;&lt;span&gt; tag as, by default, it uses a distroless Java 8 image. However, I have used Java 11, so I have explicitly mentioned that here. Moreover, depending upon your use case, you may want to use a different base image.&lt;/span&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;strong&gt;&amp;lt;image&amp;gt;&lt;/strong&gt; This refers to the target image that will pushed to the container registry. &lt;span&gt;I have used the Docker registry, but you can use any cloud provider(ECS, GCR, ACR) container registry.&lt;/span&gt;
&lt;/blockquote&gt;

&lt;p&gt;To use further options with the plugin, you can refer to the &lt;a title="documentation" href="https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Setting Credentials For Registry&lt;/h3&gt;

&lt;p&gt;To push an image, we would need to add registry credentials to maven settings.xml. Since we are just doing a demo, it’s ok to provide credentials this way but avoid using it as it is not secure. You may want to secure credentials as mentioned &lt;a title="here" href="https://maven.apache.org/guides/mini/guide-encryption.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;pre class="EnlighterJSRAW"&gt;&amp;lt;server&amp;gt;
    &amp;lt;id&amp;gt;registry.hub.docker.com&amp;lt;/id&amp;gt;
    &amp;lt;username&amp;gt;username&amp;lt;/username&amp;gt;
    &amp;lt;password&amp;gt;password&amp;lt;/password&amp;gt;
&amp;lt;/server&amp;gt;&lt;code class="language-xml"&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Building An Image&lt;/h3&gt;

&lt;p&gt;To build an image, we can do it in the following ways.&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;
&lt;strong&gt;IDE. &lt;/strong&gt;For example, in IntelliJ, you can go to maven view of your project, then go under Plugins&amp;gt;jib, then right-click and run the maven build. You may want to create an IntelliJ run configuration that can run maven goals like clean, compile, etc., then push your image.&lt;img class="size-full wp-image-36689" src="https://res.cloudinary.com/practicaldev/image/fetch/s--GvHlHFMo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://foojay.io/wp-content/uploads/2020/12/Screenshot-2020-12-29-at-12.10.08-AM.png" alt="Intellij screenshot" width="458" height="334"&gt;
&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Using the command line. &lt;/strong&gt;Just run the below command to build an image of your application. Make sure you have Maven installed first:
&lt;pre class="EnlighterJSRAW"&gt;mvn compile jib:build&lt;/pre&gt;
It will compile, build, and then push your application's image to the configured container registry.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following is the output:&lt;/p&gt;

&lt;pre class="EnlighterJSRAW"&gt;ashish@MacBook-Air springboot % mvn compile jib:build
[INFO] Scanning for projects…
[INFO]
[INFO] — — — — — — — — — — &amp;lt; com.example:spring-boot-jib &amp;gt; — — — — — — — — — — -
[INFO] Building springboot 0.0.1-SNAPSHOT
[INFO] — — — — — — — — — — — — — — — — [ jar ] — — — — — — — — — — — — — — — — -
[INFO]
[INFO] — — maven-resources-plugin:3.1.0:resources (default-resources) @ spring-boot-jib — -
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] — — maven-compiler-plugin:3.8.1:compile (default-compile) @ spring-boot-jib — -
[INFO] Nothing to compile — all classes are up to date
[INFO]
[INFO] — — jib-maven-plugin:2.6.0:build (default-cli) @ spring-boot-jib — -
[WARNING] ‘mainClass’ configured in ‘maven-jar-plugin’ is not a valid Java class: ${start-class}
[INFO]
[INFO] Containerizing application to registry.hub.docker.com/hiashish/spring-boot-jib-image…
[WARNING] Base image ‘gcr.io/distroless/java:11’ does not use a specific image digest — build may not be reproducible
[INFO] Using credentials from Maven settings file for registry.hub.docker.com/hiashish/spring-boot-jib-image
[INFO] Using base image with digest: sha256:b25c7a4f771209c2899b6c8a24fda89612b5e55200ab14aa10428f60fd5ef1d1
[INFO]
[INFO] Executing tasks:
[INFO]
[INFO] Executing tasks:
[INFO]
[INFO] Executing tasks:
[INFO] [======= ] 25.0% complete
[INFO]
[INFO] Executing tasks:
[INFO] [======= ] 25.0% complete
[INFO] &amp;gt; pushing blob sha256:6508f436f385b3751366f90b6…
[INFO]
[INFO] Executing tasks:
[INFO] [======= ] 25.0% complete
[INFO] &amp;gt; pushing blob sha256:6508f436f385b3751366f90b6…
[INFO] &amp;gt; pushing blob sha256:c5e22041fc97b838b93a2e18d…
[INFO]
[INFO] Executing tasks:
[INFO] [======= ] 25.0% complete
[INFO] &amp;gt; pushing blob sha256:6508f436f385b3751366f90b6…
[INFO] &amp;gt; pushing blob sha256:c5e22041fc97b838b93a2e18d…
[INFO] &amp;gt; pushing blob sha256:b25902383f9ee26808b68ca62…
[INFO]
[INFO] Executing tasks:
[INFO] [======= ] 25.0% complete
[INFO] &amp;gt; pushing blob sha256:6508f436f385b3751366f90b6…
[INFO] &amp;gt; pushing blob sha256:c5e22041fc97b838b93a2e18d…
[INFO] &amp;gt; pushing blob sha256:b25902383f9ee26808b68ca62…
[INFO] &amp;gt; checking base image layer sha256:31eb28996804…
[INFO]
[INFO] Executing tasks:
[INFO] [======== ] 27.8% complete
[INFO] &amp;gt; pushing blob sha256:c5e22041fc97b838b93a2e18d…
[INFO] &amp;gt; pushing blob sha256:b25902383f9ee26808b68ca62…
[INFO] &amp;gt; checking base image layer sha256:31eb28996804…
[INFO]
[INFO] Executing tasks:
[INFO] [========= ] 30.6% complete
[INFO] &amp;gt; pushing blob sha256:c5e22041fc97b838b93a2e18d…
[INFO] &amp;gt; checking base image layer sha256:31eb28996804…
[INFO]
[INFO] Executing tasks:
[INFO] [========== ] 33.3% complete
[INFO] &amp;gt; checking base image layer sha256:31eb28996804…
[INFO]
[INFO] Executing tasks:
[INFO] [=========== ] 35.0% complete
[INFO]
[INFO] Executing tasks:
[INFO]
[INFO]
[INFO]
[INFO] Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, com.jib.example.spring.SpringbootApplication]
[INFO]
[INFO] Built and pushed image as registry.hub.docker.com/hiashish/spring-boot-jib-image
[INFO] Executing tasks:
[INFO] [=========================== ] 91.7% complete
[INFO] &amp;gt; launching layer pushers
[INFO]
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
[INFO] BUILD SUCCESS
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
[INFO] Total time: 8.746 s
[INFO] Finished at: 2020–11–16T02:34:33+05:30
[INFO] — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —&lt;/pre&gt;

&lt;h3&gt;Running An Image&lt;/h3&gt;

&lt;p&gt;We have successfully pushed the image (image name:spring-boot-jib-image) to a Docker registry. Now we can run the image using Docker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pYGp05Ja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://foojay.io/wp-content/uploads/2020/12/Screenshot-2020-12-28-at-11.41.02-PM-700x147.png" class="article-body-image-wrapper"&gt;&lt;img class="size-medium wp-image-36688" src="https://res.cloudinary.com/practicaldev/image/fetch/s--pYGp05Ja--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://foojay.io/wp-content/uploads/2020/12/Screenshot-2020-12-28-at-11.41.02-PM-700x147.png" alt="" width="700" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see that our application is running inside a container. Now just run the curl command, and you can see that we got a hello message from our containerized spring-boot application.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-shell"&gt;curl localhost:8080/hello
Hello From Spring-Boot Jib&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Quick Demo&lt;/h3&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/g2RaApg2zP8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;In this article, we have learned how we can containerize our Java applications without Docker. Additionally, with Jib, you can build images using Docker, but that’s not the X factor.&lt;/p&gt;

&lt;p&gt;Other benefits of using Jib for your Java applications include that it's super easy to integrate with Java applications, producing faster builds, reproducible builds, community support, etc.&lt;/p&gt;

&lt;p&gt;You can go through this &lt;a title="link" href="https://www.google.com/amp/s/cloudblog.withgoogle.com/products/gcp/introducing-jib-build-java-docker-images-better/amp/"&gt;link&lt;/a&gt; to know about Jib's benefits in detail.&lt;/p&gt;

&lt;h4&gt;Support me&lt;/h4&gt;

&lt;p&gt;If you like what you've just read, you can buy me a coffee! :-)&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/meashish" rel="noopener"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rb9xKs4G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Further Reading&lt;/h4&gt;

&lt;p&gt;You can continue reading some of my previous &lt;a href="https://ashishtechmill.com"&gt;articles&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>docker</category>
      <category>jib</category>
      <category>java</category>
    </item>
  </channel>
</rss>
