<?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: imphilippesimo</title>
    <description>The latest articles on DEV Community by imphilippesimo (@imphilippesimo).</description>
    <link>https://dev.to/imphilippesimo</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%2F322772%2Fe2716315-31f2-4203-980e-2b99ce999d84.png</url>
      <title>DEV Community: imphilippesimo</title>
      <link>https://dev.to/imphilippesimo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imphilippesimo"/>
    <language>en</language>
    <item>
      <title>Testing your GraphQL APIs in a Spring-boot app</title>
      <dc:creator>imphilippesimo</dc:creator>
      <pubDate>Sat, 13 Jun 2020 16:57:43 +0000</pubDate>
      <link>https://dev.to/imphilippesimo/testing-your-graphql-apis-in-a-spring-boot-app-ki7</link>
      <guid>https://dev.to/imphilippesimo/testing-your-graphql-apis-in-a-spring-boot-app-ki7</guid>
      <description>&lt;p&gt;This article is the fourth article of the series &lt;a href="https://medium.com/@philippechampion58/grapql-from-theory-to-real-world-with-spring-boot-d6b46a28027b?source=friends_link&amp;amp;sk=265f0f4063dbea9780de4a55e8370b14"&gt;GraphQL, from theory to real-world with Spring-boot&lt;/a&gt;. But don’t worry, The stories are designed to be consumed independently from the other stories. You just have to grab the current state of the project by doing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;-n&lt;/span&gt; https://github.com/zero-filtre/springboot-graphql-error-handling.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;springboot-graphql-error-handling

git checkout 71d5f771bf9a6feaf8a5b7f62947442aace2b127
git switch &lt;span class="nt"&gt;-c&lt;/span&gt; my_experimental_branch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In this article, we will see how we can test the resources that we have defined in the project.&lt;/p&gt;

&lt;p&gt;You can check out the corresponding video here:&lt;/p&gt;

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

&lt;p&gt;We want to make sure the tests are fast, reliable and easy to understand.&lt;/p&gt;

&lt;p&gt;If you have not cloned our project, then you may need these dependencies in your pom.xml&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.graphql-java-kickstart&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;graphql-spring-boot-starter-test&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;6.0.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We have three resources to test, we will then define three GraphQL queries to load from our resources folder.&lt;/p&gt;

&lt;p&gt;If it’s not already done, create this directory in your project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/test/resources/graphql&lt;/code&gt; then create these 3 request file in it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mypassword"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
create-user.graphql





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation{
    deleteUser(username: "johndoe"){
        id
        username
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
delete-user.graphql





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query{
    getUser(username: "johndoe",password: "mypassword"){
        id
        username
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
get-user.graphql




&lt;p&gt;In our test package we will create 2 classes :&lt;br&gt;
One for testing mutations and another one to test queries.&lt;/p&gt;


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





&lt;p&gt;Let’s dissect what is happening here.&lt;/p&gt;

&lt;p&gt;We want to test the write requests: AKA the Mutation resolvers.&lt;/p&gt;

&lt;p&gt;As we are using &lt;code&gt;graphql-spring-boot-starter-test&lt;/code&gt;we are taking advantage of the embedded JUnit 5 Jupiter engine, and some useful tools to set up graphql easily.&lt;/p&gt;

&lt;p&gt;Especially the &lt;code&gt;@GraphQLTest&lt;/code&gt;annotation that is loading only a slice of the Spring-context that is needed for our tests to run.&lt;/p&gt;

&lt;p&gt;This is particularly interesting as our tests need to run fast and not wait for the full heavy Spring context to load.&lt;/p&gt;

&lt;p&gt;Another interesting tool is the &lt;code&gt;GraphQLTestTemplate&lt;/code&gt; class that helps us send real GraphQL queries, that we have defined earlier, to tests our resolvers.&lt;/p&gt;

&lt;p&gt;As we want our tests to run as fast as possible, we do not need to load the real underlying beans needed for our resolvers, talking here about the UserService bean. We will just mock them, and tell the mock how to behave when a specific method is called by the resolver.&lt;/p&gt;

&lt;p&gt;Finally, as we have secured our GraphQL resources, we have to use Spring-security to mock users with adequate rights.&lt;/p&gt;

&lt;p&gt;We are following the same logic for testing the read request resolvers, AKA : Query resolvers&lt;/p&gt;


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




&lt;p&gt;And that’s all you have to do to test that your resolvers are responding to the requests you expect them to.&lt;/p&gt;

&lt;p&gt;This is the end of the series, I hope you enjoyed it.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

&lt;p&gt;Feedback is a gift 🎁.&lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
      <category>springboot</category>
      <category>api</category>
    </item>
    <item>
      <title>Secure your GraphQL API within a Spring-Boot App</title>
      <dc:creator>imphilippesimo</dc:creator>
      <pubDate>Sat, 13 Jun 2020 16:56:57 +0000</pubDate>
      <link>https://dev.to/imphilippesimo/secure-your-graphql-api-within-a-spring-boot-app-1ecj</link>
      <guid>https://dev.to/imphilippesimo/secure-your-graphql-api-within-a-spring-boot-app-1ecj</guid>
      <description>&lt;p&gt;This is the third episode of the series &lt;a href="https://medium.com/@philippechampion58/grapql-from-theory-to-real-world-with-spring-boot-d6b46a28027b?source=friends_link&amp;amp;sk=265f0f4063dbea9780de4a55e8370b14"&gt;GraphQL, from Theory to Real-World with Spring boot&lt;/a&gt;. The episodes are designed to be consumed independently, so feel free to start from what interest ou the most.&lt;/p&gt;

&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;In the &lt;a href="https://medium.com/@philippechampion58/understanding-graphql-error-handling-mechanisms-in-spring-boot-604301c9bedb?source=friends_link&amp;amp;sk=1d97101ee639e362b86fad68c2cc2a14"&gt;previous article&lt;/a&gt;, we’ve exposed a set of resources via a GraphQL API. Now we want to secure them to prevent unauthenticated and unauthorized access.&lt;/p&gt;

&lt;h4&gt;
  
  
  TL;DR
&lt;/h4&gt;

&lt;p&gt;Check the corresponding video.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;NOTE: Reading the previous article IS NOT mandatory, they are designed to be consumed independently by just checking out the &lt;a href="https://github.com/zero-filtre/springboot-graphql-error-handling"&gt;codebase on GitHub.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Spring security offers us the &lt;code&gt;WebSecurityConfigurerAdapter::configure&lt;/code&gt; method to configure our app security. It gives us a way to define the access level of some resources based on URLs. Unfortunately, this is not a mechanism that fits well with the GraphQL protocol as it does with REST APIs.&lt;/p&gt;

&lt;p&gt;Actually, graphQL is using only one endpoint, usually &lt;code&gt;/graphql.&lt;/code&gt; Hence we cannot secure our resources based on URLs. As we want some resources to be either accessed only by administrators, or by authenticated users or even opened to the public.&lt;/p&gt;

&lt;p&gt;But it becomes possible if we use annotations on resolvers methods, coupled with Aspect-Oriented Programming (AOP), and that’s what we are going to do.&lt;/p&gt;

&lt;p&gt;So, at the end of this article, you will know how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Set up an aspect with Spring AOP,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use aspect-oriented programming coupled with custom annotations to secure your resources,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write tests to check your GraphQL API&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Project Setup
&lt;/h1&gt;

&lt;p&gt;Clone the &lt;a href="https://github.com/zero-filtre/springboot-graphql-error-handling"&gt;code base&lt;/a&gt; that we had in the &lt;a href="https://medium.com/@philippechampion58/understanding-graphql-error-handling-mechanisms-in-spring-boot-604301c9bedb?source=friends_link&amp;amp;sk=1d97101ee639e362b86fad68c2cc2a14"&gt;previous article&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;-n&lt;/span&gt; https://github.com/zero-filtre/springboot-graphql-error-handling.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;springboot-graphql-error-handling/

git checkout bd7a0b5c039c610de9c8355be0d1c5f5e5484655

git switch &lt;span class="nt"&gt;-c&lt;/span&gt; my_experimental_branch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We will make the resources:&lt;br&gt;
&lt;strong&gt;&lt;code&gt;createUser(username:string, password:string)&lt;/code&gt;&lt;/strong&gt; public,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;getUser(username:string, password:string)&lt;/code&gt;&lt;/strong&gt; available for authenticated users only, and we will create an additional resource:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;deleteUser(username:string)&lt;/code&gt;&lt;/strong&gt;, to be available for admin users only.&lt;/p&gt;

&lt;p&gt;Add the following dependencies to the &lt;code&gt;pom.xml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;...
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-security&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-aspects&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.security&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-security-test&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;junit&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;junit&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;scope&amp;gt;&lt;/span&gt;test&lt;span class="nt"&gt;&amp;lt;/scope&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then we add the additional &lt;code&gt;deleteUser&lt;/code&gt; resource which matches the following resolver method in &lt;code&gt;UserMutation.java&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;deleteUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Don’t forget to define the &lt;code&gt;UserService::delete&lt;/code&gt; method, which just removes the user corresponding to that username from the in-memory &lt;code&gt;List&amp;lt;User&amp;gt; users&lt;/code&gt; and returns information about the deleted user.&lt;/p&gt;

&lt;p&gt;Add &lt;strong&gt;deleteUser&lt;/strong&gt; resource spec to the schema definition file: &lt;code&gt;src/main/resources/UserQL.graphqls&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Securing the resources
&lt;/h1&gt;

&lt;p&gt;The strategy consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Authorizing all requests related to GraphQL: &lt;code&gt;/graphql&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, thanks to &lt;strong&gt;custom annotations&lt;/strong&gt;, specify, at the method level in resolvers, which methods are public, which ones &lt;strong&gt;should be accessed only by authenticated users&lt;/strong&gt;, and which ones &lt;strong&gt;should only be accessed by users with specific roles such as ADMIN.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whilst with aspects, we will check if our annotations are applied or not and throw exceptions accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s create the security configuration file: &lt;code&gt;SecurityConfig.java&lt;/code&gt;&lt;/p&gt;


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



&lt;p&gt;This config tells our app to authorize all requests related to GraphQL so that we can check them at the resolver level with annotations.&lt;/p&gt;

&lt;p&gt;We will have two annotations:&lt;br&gt;
&lt;code&gt;@AdminSecured&lt;/code&gt; appended to admin resources, and&lt;br&gt;
&lt;code&gt;@Unsecured&lt;/code&gt; appended to public resources.&lt;br&gt;
All other endpoints will, by default, need authenticated users access.&lt;br&gt;
It’s always better to forget to make a resource unsecured than to forget to secure it 😁&lt;/p&gt;

&lt;p&gt;AdminSecured.java&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="cm"&gt;/**
 * This annotation will trigger Admin security check for
 * the GraphQL resolver method where it is marked.
 */&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RetentionPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ElementType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;METHOD&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;AdminSecured&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Unsecured.java&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="cm"&gt;/**
 * This annotation will disable security check for
 * the GraphQL resolver method where it is marked.
 */&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RetentionPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ElementType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;METHOD&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Unsecured&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now go on and annotate the resolver methods accordingly:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Unsecured&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@AdminSecured&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;deleteUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;UserQuery::getUser&lt;/code&gt; will be set as secured by default.&lt;/p&gt;

&lt;p&gt;Let’s define the aspect that will scan these annotations.&lt;br&gt;
First, we need to Enable AOP in the main application class, &lt;br&gt;
by adding &lt;code&gt;@EnableAspectJAutoProxy&lt;/code&gt; annotation like so:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="nd"&gt;@EnableAspectJAutoProxy&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleGraphqlErrorHandlingApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SampleGraphqlErrorHandlingApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then the aspect class… But wait! ☝, What’s an aspect? 🤔&lt;/p&gt;

&lt;p&gt;Aspects are related to Aspect-Oriented Programming (AOP) which gives you a way to encapsulate or modularize a behavior that is transversal and repeated across several types of objects and that is, normally, not easy to encapsulate in its own module.&lt;/p&gt;

&lt;p&gt;Usually, those behaviors (logging, caching, transaction management…) are not related to business logic and they are so-called aspects.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An aspect is a common feature that’s typically scattered across methods, classes, object hierarchies, or even entire object models [3] .&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example:&lt;br&gt;
AOP provides you with programmatic control to specify that you want calls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To all methods annotated &lt;code&gt;@Timed&lt;/code&gt; to trigger a timer before executing the actual body of that code,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To all methods classes in the package &lt;code&gt;xxx.bank.account&lt;/code&gt; to trigger a specific additional security check,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;etc&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without repeating yourself 😎&lt;/p&gt;

&lt;p&gt;We are going to do something similar with our Aspect.&lt;/p&gt;

&lt;p&gt;Yes, you have guessed it right, our aspect is about security check based on annotations.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SecurityGraphQLAspect.java&lt;/code&gt;&lt;/p&gt;


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



&lt;p&gt;Don’t worry, It seems complicated but it’s actually pretty simple.&lt;br&gt;
Let’s go through each part of it to understand what it’s being done here.&lt;/p&gt;

&lt;p&gt;First, As we defined this spring component as &lt;code&gt;@Aspect&lt;/code&gt;, it becomes an interceptor and we want it to be the first to be triggered, before any other interceptor, since it is our security guarantor. That’s why we use &lt;code&gt;@Order(1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The first method &lt;code&gt;doSecurityCheck&lt;/code&gt;is annotated with &lt;code&gt;@Before&lt;/code&gt;which is an &lt;strong&gt;&lt;em&gt;Advice&lt;/em&gt;&lt;/strong&gt;, which means, according to AOP terminology: &lt;strong&gt;action taken by the aspect at a specific point during the execution of the program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@Before&lt;/code&gt; advice lets the action being executed before the specified &lt;strong&gt;&lt;em&gt;PointCut&lt;/em&gt;&lt;/strong&gt;s, which helps to &lt;strong&gt;categorize elements of the program that the aspect will watch.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;doSecurityCheck&lt;/code&gt;is executed before &lt;strong&gt;all GraphQL resolvers methods&lt;/strong&gt; that &lt;strong&gt;are defined within our project&lt;/strong&gt; and that &lt;strong&gt;are not annotated as unsecured&lt;/strong&gt;. These categories are then defined with the help of &lt;code&gt;@PointCut&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;doSecurityCheck&lt;/code&gt;checks the Spring security context to make sure the user is authenticated.&lt;/p&gt;

&lt;p&gt;Similarly: &lt;code&gt;doAdminSecurityCheck&lt;/code&gt; is executed before *&lt;em&gt;all methods annotated as AdminSecured. *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;doAdminSecurityCheck&lt;/code&gt;checks the Spring security context to make sure the user has the ADMIN role.&lt;/p&gt;

&lt;p&gt;This is the code for the referenced &lt;code&gt;UnauthenticatedAccessException.java&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnauthenticatedAccessException&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;GraphQLError&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UnauthenticatedAccessException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SourceLocation&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getLocations&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ErrorClassification&lt;/span&gt; &lt;span class="nf"&gt;getErrorType&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;That’s it! 🏁&lt;/p&gt;

&lt;p&gt;Now let’s start the app, launch &lt;a href="http://locahost:8080/graphiql"&gt;http://locahost:8080/graphiql&lt;/a&gt; and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a user:&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Everything works as expected ✌🏾.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete that user:&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;We do not have the right to do that as expected ✌🏾.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get users:&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;We need to log in first as expected ✌🏾.&lt;/p&gt;

&lt;p&gt;Let’s test the remaining cases programmatically so that you can automate it in a pipeline and earn some time.&lt;/p&gt;

&lt;p&gt;GraphQLSecurityTests.java&lt;/p&gt;


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



&lt;p&gt;Notice that we restart the context after each test method with &lt;code&gt;@DirtiesContext&lt;/code&gt; to make sure every method runs in a clean, not polluted context. But you should not abuse this, as it increases considerably your tests execution time.&lt;br&gt;
Run the test and should have a 100% success.&lt;/p&gt;

&lt;p&gt;Now our endpoints are secured 😎.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;GraphQL APIs are great but are different in so many ways from REST APIs, and the way to handle the security is no exception.&lt;/p&gt;

&lt;p&gt;That’s why in this article, we saw how to use aspect-oriented programming coupled with custom annotations to secure our resources. Additionally, we also wrote tests to check the whole stuff.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed it. &lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://medium.com/@philippechampion58/testing-your-graphql-apis-in-a-spring-boot-app-9fe02ebccc35?source=friends_link&amp;amp;sk=c91ff02c10402469f6e9c3824a7d89cd"&gt;next article&lt;/a&gt;, we will describe a strategy and apply a strategy to write fast, bulletproof tests for your GraphQL APIs with Spring boot.&lt;/p&gt;

&lt;p&gt;Don’t forget, Feedback is a gift 🎁!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;References:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;[1]&lt;a href="https://docs.spring.io/spring/docs/2.0.x/reference/aop.html"&gt;https://docs.spring.io/spring/docs/2.0.x/reference/aop.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2]&lt;a href="https://mi3o.com/spring-graphql-security/"&gt;https://mi3o.com/spring-graphql-security/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3]&lt;a href="https://docs.jboss.org/aop/1.0/aspect-framework/userguide/en/html/what.html"&gt;https://docs.jboss.org/aop/1.0/aspect-framework/userguide/en/html/what.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>java</category>
      <category>springboot</category>
      <category>api</category>
    </item>
    <item>
      <title>Understanding GraphQL Error Handling mechanisms in Spring-boot</title>
      <dc:creator>imphilippesimo</dc:creator>
      <pubDate>Sat, 13 Jun 2020 16:53:11 +0000</pubDate>
      <link>https://dev.to/imphilippesimo/understanding-graphql-error-handling-mechanisms-in-spring-boot-f93</link>
      <guid>https://dev.to/imphilippesimo/understanding-graphql-error-handling-mechanisms-in-spring-boot-f93</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Overview&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This article is the second part of the series GraphQL, from Theory to real-world with Spring boot.&lt;/p&gt;

&lt;p&gt;Today’s episode is about setting up your Spring-boot project to host your first GraphQL API entry points then call them using the web-based tool GraphiQL.&lt;/p&gt;

&lt;p&gt;It also aims to bring an in-depth understanding of how the &lt;a href="https://github.com/graphql-java/graphql-java"&gt;Graphql Java Implementation&lt;/a&gt; (graphql-java) deals with error handling and especially how to rely on that, by using the &lt;a href="https://github.com/graphql-java-kickstart/graphql-spring-boot"&gt;GraphQL Spring Framework boot starter&lt;/a&gt;, to handle efficiently errors within our app, as this is an aspect that is often overlooked by early graphql adopters.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;TL;DR&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Check the corresponding video out:&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lxOXDI_dvt8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Before we start, let’s introduce some context.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;GraphQL quick summary&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;GraphQL is a specification that defines not only a new query language for APIs but also how data is returned in response to these queries.&lt;br&gt;
It is an alternative to using Restful APIs in the sense that it solves some of their drawbacks with new features such as these described ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The client has full control over the data returned to him, he receives only what he needs, no more, no less. No unnecessary data is therefore loaded onto the network. No over-etching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The client can request several resources at once in a single request, no need to send multiple requests. Ideal for slow mobile connections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server defines what is possible or not with the notion of types, to force the client to request only what is possible.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;With great power comes great responsibilities&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;According to the features mentioned above, the client must be highly considered when setting up such an API. &lt;/p&gt;

&lt;p&gt;It is more than important to return a response format that is consistent and predictable across several scenarios, to make it easier for the customer to consume the response.&lt;/p&gt;

&lt;p&gt;According to the specification, a GraphQL response should follow this pattern:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A GraphQL response might always have the HTTP status 200 OK.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HTTP error codes are not relevant when using GraphQL because,&lt;br&gt;
If a request fails, the JSON payload of the server’s response will contain a root field called &lt;em&gt;“errors”&lt;/em&gt; that contains precise information about the problems that occurred on the server-side.&lt;/p&gt;

&lt;p&gt;Moreover, since GraphQL allows for multiple operations to be sent in the same request, well, it’s possible that a request fails partially and returns actual data and errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The response body could contain the following fields:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;“data”&lt;/em&gt;&lt;/strong&gt;: where the data resulting from the operation reside.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;“errors”&lt;/em&gt;&lt;/strong&gt;: where all the errors are filled in.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;“extensions”&lt;/em&gt;&lt;/strong&gt;: for additional information about the response&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;em&gt;"errors"&lt;/em&gt; field, should contain the following fields :&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;"message"&lt;/em&gt;&lt;/strong&gt;: a key describing the error&lt;br&gt;
&lt;strong&gt;&lt;em&gt;"locations"&lt;/em&gt;&lt;/strong&gt;: a list of graph coordinates where the errors have occurred.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;"path"&lt;/em&gt;&lt;/strong&gt;: a key describing the absolute path from the root of the graph to the field where an error has occurred.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;"extensions"&lt;/em&gt;&lt;/strong&gt; key for the metadata related to the errors.&lt;/p&gt;

&lt;p&gt;You can learn more about GraphQL response format by referring to the &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fspec.graphql.org%2FJune2018%2F%23sec-Response"&gt;specification part that deals with this topic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As far as we are concerned, we will just focus on the &lt;strong&gt;&lt;em&gt;"errors"&lt;/em&gt;&lt;/strong&gt; key.&lt;/p&gt;

&lt;p&gt;By relying on the graphql-java and graphql-spring-boot within a spring-boot application, we will dissect the underlying mechanism of errors handling within these libraries to let you know what are your possibilities when it comes to customizing some of the default error handling mechanisms.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Application Set up&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;We will use a simple spring-boot &lt;code&gt;sample-graphql-error-handling&lt;/code&gt; that will expose two endpoints:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;createUser(username:string, password:string)&lt;/code&gt; that fails if a user is already registered with the same username.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getUser(username:string,password:string)&lt;/code&gt; that fails if no user is existing for the given username.&lt;/p&gt;

&lt;p&gt;Generate the project using &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fstart.spring.io%2F"&gt;Spring Initializr&lt;/a&gt; and add the following dependencies to the pom.xml file:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
Minimal maven dependencies to enable graphql implementation within a spring boot app




&lt;p&gt;Our User model Class: User.java&lt;/p&gt;


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




&lt;p&gt;The Schema definition file: &lt;code&gt;src/main/resources/UserQL.graphqls&lt;/code&gt;&lt;/p&gt;


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




&lt;p&gt;The schema speaks for itself, we will have a read request &lt;code&gt;getUser&lt;/code&gt; which will return a &lt;code&gt;User&lt;/code&gt; corresponding to the &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; given as parameters, and a write request which will register a &lt;code&gt;User&lt;/code&gt; with its credentials as parameters.&lt;/p&gt;

&lt;p&gt;We will use a service class, acting as our business logic that will maintain a list of in-memory users. This service will be injected into our resolvers later.&lt;/p&gt;


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




&lt;p&gt;The &lt;code&gt;createUser&lt;/code&gt; method will return a &lt;code&gt;UserAlreadyExistsException&lt;/code&gt; if a user already exists. &lt;/p&gt;

&lt;p&gt;Similarly, the &lt;code&gt;getUsermethod&lt;/code&gt; will return a &lt;code&gt;UserNotFoundException&lt;/code&gt; in case no user is found.&lt;/p&gt;

&lt;p&gt;Next, we have the code of our exceptions:&lt;/p&gt;


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





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




&lt;p&gt;We will rely on these customized exceptions to return relevant information to the customer.&lt;/p&gt;

&lt;p&gt;Finally, the resolvers code:&lt;/p&gt;


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





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




&lt;p&gt;Now that the project is set up, we can start sending the requests and analyze the errors. &lt;/p&gt;

&lt;p&gt;Run the spring boot app and launch the graphiql tool within the browser with: &lt;code&gt;http://localhost:8080/graphiql&lt;/code&gt; if you are running on the local machine with the default spring boot app port.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;The generic error (case#1)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Within the graphiql tool, let's start by creating a user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pwd"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Everything is OK and the user is indeed created as confirmed by the answer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vWS4Y9YN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fhc3kxbejx9e7h9zmnrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vWS4Y9YN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fhc3kxbejx9e7h9zmnrr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we try to get a non-existing user:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"def"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RRN2wicz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1300/0%2A30BZQYWDtA5MI1Yj" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RRN2wicz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1300/0%2A30BZQYWDtA5MI1Yj" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not only are the details as defined by the specification missing, but the error message is also inconsistent, as it indicates a server-side error yet it is a client-side error.&lt;/p&gt;

&lt;p&gt;Also, if we try to create a user that is already existing:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pwd"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RRN2wicz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1300/0%2A30BZQYWDtA5MI1Yj" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RRN2wicz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1300/0%2A30BZQYWDtA5MI1Yj" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s consider what just happened as &lt;strong&gt;CASE #1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;CASE #2&lt;/strong&gt; : We need to customize the information according to the error that occurred while giving the client additional information about what happened in the backend so that he can react accordingly.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;Customizing errors (case#2)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;We've already taken a step forward by defining and throwing problem-related customized exceptions. However, these exceptions need to be transformed into GraphQL errors that respect the standard format before being sent to the client.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;graphql-java&lt;/code&gt; provides the &lt;code&gt;GraphQLError&lt;/code&gt; interface representing a GraphQL standard error that our exceptions will implement.&lt;/p&gt;

&lt;p&gt;Our exceptions become:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
UserAlreadyExistsException.java as GraphQLError






&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
UserNotFoundException.java as GraphQLError with extra data
 



&lt;p&gt;Overriding &lt;code&gt;getLocations()&lt;/code&gt; and &lt;code&gt;getErrorType()&lt;/code&gt; is mandatory.&lt;/p&gt;

&lt;p&gt;We will just return &lt;code&gt;null&lt;/code&gt;in these methods because they are ignored by the default error handler anyway. &lt;br&gt;
We will see why later.&lt;/p&gt;

&lt;p&gt;In the case of wrong identification data, we want to add an &lt;em&gt;&lt;strong&gt;“invalidField”&lt;/strong&gt;&lt;/em&gt; field under the key &lt;em&gt;&lt;strong&gt;“extensions”&lt;/strong&gt;&lt;/em&gt; of the error to indicate to the customer which field is in error and needs to be corrected.&lt;/p&gt;

&lt;p&gt;This is why we redefine the &lt;code&gt;getExtensions()&lt;/code&gt; method in &lt;code&gt;UserNotFoundException&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Don’t forget to change the instantiation of the exception in &lt;code&gt;UserService.java&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserNotFoundException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nc"&gt;We&lt;/span&gt; &lt;span class="n"&gt;were&lt;/span&gt; &lt;span class="n"&gt;unable&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;provided&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Let’s start the application again and run the same test scenario with graphiql to compare the results.&lt;/p&gt;

&lt;p&gt;Let’s start by creating a user, the answer is, unsurprisingly, this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CiC4pJWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1256/0%2AZ2sAOf2HBKv3cHj8" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CiC4pJWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1256/0%2AZ2sAOf2HBKv3cHj8" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, if you try to retrieve a user that doesn’t exist, the request results in the following error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LULjpOHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2ADMisGK5Fd97sOMKu" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LULjpOHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2ADMisGK5Fd97sOMKu" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note the invalid field present in the extensions block of the result.&lt;/p&gt;

&lt;p&gt;Also, If we try to create a user with an existing username, the response is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pcvcImws--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2AgF2OoTMaQs1LiqIL" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pcvcImws--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2AgF2OoTMaQs1LiqIL" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s dissect what just happened in both cases #1 and #2:&lt;/p&gt;

&lt;p&gt;When we throw an exception while fetching data:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. The exception is handled by default by the &lt;code&gt;SimpleDataFetcherExceptionHandler&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The handler wraps 4 things: the thrown custom exception (the RuntimeException), the exception message, the error locations, and the extensions, within an ExceptionWhileDataFetchingerror (which is an implementation of the GraphQLErrorinterface).&lt;br&gt;
Then, the ExceptionWhileDataFetching is added to the list of errors of the query result. As we can see in the following &lt;a href="https://github.com/graphql-java/graphql-java/blob/master/src/main/java/graphql/execution/SimpleDataFetcherExceptionHandler.java"&gt;SimpleDataFetcherExceptionHandler&lt;/a&gt; code.&lt;/p&gt;


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





&lt;p&gt;At line 10, a new &lt;code&gt;ExceptionWhileDataFetching&lt;/code&gt; is constructed with the error path, our exception, and the sourceLocation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Remember I told you the methods getLocations() and getErrorType() of our exception were ignored?&lt;br&gt;
Well here’s why:&lt;/em&gt;&lt;/p&gt;


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



&lt;p&gt;&lt;em&gt;In this code snippet from the &lt;a href="https://github.com/graphql-java/graphql-java/blob/master/src/main/java/graphql/ExceptionWhileDataFetching.java"&gt;ExceptionWhileDataFetching&lt;/a&gt; class, only the methods getMessage() and getExtensions() are called, the path and the sourceLocation are already provided upon class instantiation.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. The DefaultGraphQLErrorHandler
&lt;/h3&gt;

&lt;p&gt;After the &lt;code&gt;SimpleDataFetcherExceptionHandler&lt;/code&gt; process, another handler, defined by the &lt;strong&gt;graphql-spring-boot&lt;/strong&gt; library comes into action to handle the returned list of errors.&lt;br&gt;
He is the &lt;code&gt;GraphQLErrorHandler&lt;/code&gt;: the default implementation is the &lt;code&gt;DefaultGraphQLErrorHandler&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These 2 steps can be illustrated as follows: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MZFxlieh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AkT6gYRkoJycrhbg-0TjuMQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MZFxlieh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AkT6gYRkoJycrhbg-0TjuMQ.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
The Simple DataFetcherExceptionHandler process



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4k2AVJU0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2Ayea_Jb-2wYm5q-kta951Tw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4k2AVJU0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2Ayea_Jb-2wYm5q-kta951Tw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
The DefaultGraphQLErrorHandler process



&lt;p&gt;&lt;strong&gt;In case#1&lt;/strong&gt;: Our custom exceptions &lt;strong&gt;were not&lt;/strong&gt; instances of &lt;strong&gt;GraphQLErrors&lt;/strong&gt;, the &lt;code&gt;DefaultGraphQLErrorHandler&lt;/code&gt; considered them as internal server errors, containing &lt;strong&gt;details that should not reach the client&lt;/strong&gt;. They were filtered and converted to &lt;code&gt;GenericGraphQLError&lt;/code&gt; as illustrated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In case#2&lt;/strong&gt;: Our custom exceptions &lt;strong&gt;were&lt;/strong&gt; instances of &lt;strong&gt;GraphQLErrors&lt;/strong&gt;, hence they were not reduced to Generic graphQL errors.&lt;/p&gt;

&lt;p&gt;This behavior is described in the &lt;code&gt;DefaultGraphQLErrorHandler::processErrors()&lt;/code&gt; method.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
DefaultGraphQLErrorHandler::processErrors()




&lt;p&gt;Now we clearly understand why we get such a useful error response and a valid format for &lt;strong&gt;case#2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;SimpleDataFetcherExceptionHandler&lt;/code&gt; behavior doesn’t fit your use case, you can create a &lt;code&gt;CustomDataFetcherExceptionHandler&lt;/code&gt;implementing &lt;code&gt;DataFectcherExceptionHandler&lt;/code&gt;, then define your own logic and throw something different than an &lt;code&gt;ExceptionWhileDataFetching&lt;/code&gt; GraphQLError.&lt;/p&gt;

&lt;p&gt;However, this is not something I will advise as you can find yourself breaking the rules of the GraphQL Specification by sending non-standard error messages. Unless you really understand what you are trying to implement.&lt;/p&gt;

&lt;p&gt;Besides, customizing this behavior implies modifying the query execution strategy. As graphql-spring-boot integration is relying on graphql-java to implement the query execution strategy, you will have to deal with them, which, IMHO, does not worth it, as they already implement a pretty good behavior.&lt;/p&gt;

&lt;p&gt;Similarly, If the &lt;code&gt;DefaultGraphQLErrorHandlerbehavior&lt;/code&gt; doesn’t fit your use case, you can create a &lt;code&gt;CustomGraphQLErrorHandler&lt;/code&gt; implementing &lt;code&gt;GraphQLErrorHandler&lt;/code&gt;, then define your own logic and handle GraphQLErrors differently.&lt;/p&gt;

&lt;p&gt;Let’s supposed we are not satisfied by the string: &lt;code&gt;Exception while fetching data (/xxxx)&lt;/code&gt; which is automatically appended to the error message sent to the user, and we just want our original message in the error, without any fancies. We will send our unwrapped original custom exception to the final user by defining a &lt;code&gt;CustomGraphQLErrorHandler&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Sending unwrapped exception&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;We create the CustomGraphErrorHandler as follows:&lt;/p&gt;


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




&lt;p&gt;We override the &lt;code&gt;processErrors&lt;/code&gt; method by telling the handler to: first check if the exception is an &lt;code&gt;ExceptionWhileDataFetching&lt;/code&gt;  then extract our original exception( &lt;code&gt;UserNotFoundException&lt;/code&gt;, &lt;code&gt;UserExistsException&lt;/code&gt; …) and return it. Otherwise, the handler will just return the received exception as it is.&lt;/p&gt;

&lt;p&gt;If we try to find a non-existing user, we get the following error:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oAW4Tmad--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2ABfW6m4elgY0BEhDI" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oAW4Tmad--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/0%2ABfW6m4elgY0BEhDI" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As our exceptions are sent back to the user unwrapped, the message is now concise and precise.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;In this article, we were focusing two notions: &lt;/p&gt;

&lt;p&gt;Setting up your Spring-boot project to host your first GraphQL API entry points, &lt;/p&gt;

&lt;p&gt;Understanding how the graphql-java implementation and graphql-spring-boot handle errors triggered within an application. &lt;/p&gt;

&lt;p&gt;We have covered the following sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up a sample project&lt;/li&gt;
&lt;li&gt;Understanding the standard Graphql error response format&lt;/li&gt;
&lt;li&gt;Diving into the mechanisms behind generic graphql errors and more
tailored ones&lt;/li&gt;
&lt;li&gt;Adding additional custom information to the error&lt;/li&gt;
&lt;li&gt;Getting to know the possibilities of further error customizations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Github repo about this article is available &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2Fzero-filtre%2Fspringboot-graphql-error-handling"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://medium.com/@philippechampion58/secure-your-graphql-api-within-a-spring-boot-app-72961fbe9232?source=friends_link&amp;amp;sk=447765d64a6a7da1d4d9eec744c78e44"&gt;next article&lt;/a&gt;, we will see how to Secure our APIs with pretty simple steps.&lt;/p&gt;

&lt;p&gt;Thanks for reading, feedback is a gift 🎁.&lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
      <category>springboot</category>
      <category>api</category>
    </item>
    <item>
      <title>GraphQL, from Theory to Real-world with Spring-boot</title>
      <dc:creator>imphilippesimo</dc:creator>
      <pubDate>Sat, 13 Jun 2020 16:46:28 +0000</pubDate>
      <link>https://dev.to/imphilippesimo/graphql-from-theory-to-real-world-with-spring-boot-3lpj</link>
      <guid>https://dev.to/imphilippesimo/graphql-from-theory-to-real-world-with-spring-boot-3lpj</guid>
      <description>&lt;p&gt;This article is the first part of a series of articles that we will go through. The series is about mastering the necessary core concepts of the GraphQL Specification to set up a real-world server-side implementation example with spring boot. Each episode is designed to be consumed independently so feel free to start from what interests you the most.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL Core concepts&lt;/strong&gt; (this one) 📈&lt;br&gt;
Getting started with the core concepts of GraphQL to build a real-world example&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/imphilippesimo/understanding-graphql-error-handling-mechanisms-in-spring-boot-f93"&gt;&lt;strong&gt;First GraphQL API and Efficient graphQL error handling in Spring-boot&lt;/strong&gt;&lt;/a&gt; 🧯&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/imphilippesimo/secure-your-graphql-api-within-a-spring-boot-app-1ecj"&gt;&lt;strong&gt;Secure your graphQL APIs within a Spring-boot&lt;/strong&gt;&lt;/a&gt; ‍👮‍♂️&lt;br&gt;
Set up access control level on your APIs to define who can have access to which if your APIs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/imphilippesimo/testing-your-graphql-apis-in-a-spring-boot-app-ki7"&gt;&lt;strong&gt;Testing your graphQL APIs in a Spring-boot app&lt;/strong&gt;&lt;/a&gt; 🚀&lt;br&gt;
Writing unit and integration tests for your graphQL APIs&lt;br&gt;
Set up your Spring-boot project and expose your firsts GraphQL endpoints Get an in-depth understanding of GraphQL error handling mechanisms.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Overview&lt;/strong&gt;
&lt;/h1&gt;

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

&lt;p&gt;It is a new API Standard developed and used by Facebook since 2012 but open-sourced since 2015. It is a more flexible and powerful alternative to REST. &lt;br&gt;
GraphQL specification has a rapidly growing community and some of the popular companies that use that are Github, Coursera, Twitter, Shopify, yelp, to name only a few.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;GraphQL vs REST&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The idea behind REST is great as it advocates the usage of stateless servers and structured access to resources. But there are shortcomings such as inefficiencies and lack of flexibility encountered by developers and that's why graphQL was developed for.&lt;br&gt;
To better illustrate the differences, we will introduce the Social Shopping App (SSApp) that we are going to develop all along with this series.&lt;br&gt;
SSApp:&lt;br&gt;
Our app consists of users, browsing some shopping articles within the app that they can like and buy. Users can sell articles and follow other users so that they can check their activities on the app. That's it!&lt;br&gt;
Ok, let's come back to the illustration, consider we want to display the user home screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A9yLme8g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xmg83hrcbnhxwtq0cewf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9yLme8g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xmg83hrcbnhxwtq0cewf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To achieve this is REST:&lt;br&gt;
We need, 3 API endpoints from the server:&lt;br&gt;
&lt;code&gt;/users/&amp;lt;id&amp;gt;&lt;/code&gt;&lt;br&gt;
Returning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flkzopgz12"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Samanta Calgon"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"birthday"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"May 15, 1995"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice we just need the &lt;code&gt;name&lt;/code&gt;, but we are fetching useless additional data at this point. We are draining the user data plan. 🤦‍♂️&lt;br&gt;
Then:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/users/&amp;lt;id&amp;gt;/articles?liked=true&lt;/code&gt;&lt;br&gt;
Returning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"articles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dmflgmjlsfgs4z545"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vuicci Sweet Shirt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lorem ipsum ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"liked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dlkfjge919zzz"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Diara Eau de Parfum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dolor epsumet ..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"liked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This time also, we just need the title of the articles.&lt;br&gt;
And&lt;br&gt;
&lt;code&gt;/users/&amp;lt;id&amp;gt;/followers&lt;/code&gt;&lt;br&gt;
Returning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"followers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dlkfhosdid2e15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Klark"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"birthday"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"January 21, 1998"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"94erg48h4j"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rose"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"birthday"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"January 21, 1998"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here, we are downloading a lot of data that we don't need as well.🤦‍♂️&lt;/p&gt;

&lt;p&gt;The fact that we are getting more than the data than we essentially want is called &lt;strong&gt;over fetching&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The fact that we can't get enough information in one request, and need to send many ones to gather all information is known as the &lt;strong&gt;under fetching&lt;/strong&gt; problem.&lt;/p&gt;

&lt;p&gt;Yes, you can adapt your REST API to the screen so that it returns only the data needed for display, using the so-called View Models. &lt;/p&gt;

&lt;p&gt;By doing this, you are highly coupling your views to the endpoints. This way, each time the view will evolve, your API shall evolve too. Which is very bad for API scalability.&lt;/p&gt;

&lt;p&gt;Fortunately, we can solve the above problems with &lt;strong&gt;graphQL&lt;/strong&gt;. 🔥&lt;/p&gt;

&lt;p&gt;We can retrieve what we need by issuing only one request. GraphQL uses only one endpoint, usually &lt;code&gt;/graphql&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Sending a request in GrapQL means issuing a post request at this endpoint, and describe in the request body what data do we exactly need from the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;User(id:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flkzopgz12"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;articles(liked:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;True)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;followers&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice how we tell the server exactly what we need with expressions corresponding to the data model schema:&lt;/p&gt;

&lt;p&gt;User.name, User-&amp;gt;articles.title, User-&amp;gt;followers.name .&lt;/p&gt;

&lt;p&gt;The server will then process and match this description to the corresponding methods to get the data.&lt;/p&gt;

&lt;p&gt;Those methods are known as the &lt;strong&gt;resolvers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Resolvers will get the data from a DB, another web service, etc then package them into a JSON object and return them to the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;      
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Samanta Calgon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="nl"&gt;"articles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vuicci Sweet Shirt"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Diara Eau de Parfum"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Timiland Shoes"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lavis Jeans White Vintage"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"followers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Klark"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rose"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rick"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Josh"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The root field of the data part of a graphQL response is data , according to the graphQL specification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GraphQL vs REST in a nutshell&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No more over and under fetching,&lt;br&gt;
No need to adapt the APIs to the view which enables rapid product iterations.&lt;/p&gt;

&lt;p&gt;Moreover, GraphQL uses a strong type system to define the &lt;em&gt;cans&lt;/em&gt; and &lt;em&gt;cants&lt;/em&gt; of your API.&lt;br&gt;
You just have to define your types in a &lt;strong&gt;Schema file&lt;/strong&gt;, written in the &lt;a href="https://medium.com/r/?url=https%3A%2F%2Falligator.io%2Fgraphql%2Fgraphql-sdl%2F"&gt;Schema Definition Language&lt;/a&gt; (SDL).&lt;br&gt;
This schema will represent the contract between the Frontend and the backend teams, enabling them to work independently in an API-first like fashion.&lt;br&gt;
Now that you know why GraphQL is a better alternative to REST, we can now dive into the core concepts of GraphQL.&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;strong&gt;GraphQL Core Concepts&lt;/strong&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  The Schema Definition Language (SDL)
&lt;/h2&gt;

&lt;p&gt;It lets us define our schema, which is made up of types.&lt;br&gt;
This example illustrates a one-to-many relationship between 2 types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="c"&gt;# Value generated by the server&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c"&gt;# String,Int,ID are built-in type&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c"&gt;# ! means age is required&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;!]&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c"&gt;# A user can be have many Articles&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c"&gt;# An article is sold by a User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In GraphQL, fetched data are not fixed, as you saw earlier, you can decide to retrieve &lt;strong&gt;ONLY&lt;/strong&gt; the User articles, or retrieve &lt;strong&gt;JUST&lt;/strong&gt; the User age, or even &lt;strong&gt;JUST&lt;/strong&gt; the Users articles' title. The client decides of what he needs&lt;/p&gt;

&lt;p&gt;One important thing to notice is that, because we didn't define a field &lt;code&gt;password&lt;/code&gt; in the User type in the schema, this field is unretrievable by the client. No more need to bother with &lt;code&gt;JsonIgnore&lt;/code&gt; configurations. That's the power of the GraphQL strong type system. The server decides of what is possible or not for the client&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;The client decides of what he needs.&lt;/em&gt;
&lt;/h3&gt;
&lt;h3&gt;
  
  
  &lt;em&gt;The server decides of what is possible or not for the client.&lt;/em&gt;
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The client decides what he needs by sending requests to the server&lt;/strong&gt;&lt;br&gt;
These are the three kind of requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query&lt;/strong&gt;: Retrieve data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutation&lt;/strong&gt;: Change data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription&lt;/strong&gt;: Event-based real-time notifications&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# Query&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c"&gt;#starts with the keyword query&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUsers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# returns&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;allUsers&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;":"&lt;/span&gt;&lt;span class="n"&gt;Samanta&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Calgon&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;":"&lt;/span&gt;&lt;span class="n"&gt;Carlos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Chavez&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Mutation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c"&gt;#starts with the keyword mutation&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Miguel Reyes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"21"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# returns&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;slkdjfr96f4d&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Subscription, listening to new articles creation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;susbscription&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c"&gt;#starts with the keyword susbscription      &lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;newArticle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#When an article is created by another client, &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#while the subscription is active, this client will receives&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Marins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Jacket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;Real&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Marins&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Jacket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;refurbished&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;2015"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="err"&gt;":"&lt;/span&gt;&lt;span class="n"&gt;Carlos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Chavez&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;__The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;decides&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;what&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;possible&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;defining&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the schema__&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mentioned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;earlier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;contract&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;between&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;written&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SDL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;defines&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;capabilities&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;means&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GraphQL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Functionally, we can see types as of 2 kinds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Types to describe the data structure, custom, and built-in ones
(User, Article, String, ID, …)&lt;/li&gt;
&lt;li&gt;Types to describe the entry points exposed by the API
(Query, Mutation, and Subscription)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#Custom and buitl-in Data Structure types&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="c"&gt;# Value generated by the server&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c"&gt;# String,Int,ID are built-in type&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c"&gt;# ! means the field is required&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;!]&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c"&gt;# A user can be have many Articles&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;followers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;seller&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c"&gt;# An article is sold by a User&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="c"&gt;#Types describing entrypoints&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allUsers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#last parameter is optional&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="c"&gt;#No '!', The returned user can be empty&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c"&gt;#...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c"&gt;#Want the client to create an article ? define the operation here&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="c"&gt;#...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Subscription&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;newArticle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that you have a better vision of what is GraphQL, you are able to step through the next part which is about writing your first GraphQL API with Spring Boot.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;GraphQL is a better alternative to REST because it offers flexibility and efficiency during application development. This article aimed to prove that while explaining the core concepts of this specification.&lt;/p&gt;

&lt;p&gt;Nevertheless, GraphQL is just a specification, that needs to be implemented for both the client and server-side. We will focus on the server-side, especially with Java and Spring-boot for the next parts of this series.&lt;/p&gt;

&lt;p&gt;Feedback is a Gift 🎁!&lt;/p&gt;

</description>
      <category>java</category>
      <category>graphql</category>
      <category>springboot</category>
      <category>api</category>
    </item>
  </channel>
</rss>
