{"id":947,"date":"2022-06-03T11:35:00","date_gmt":"2022-06-03T09:35:00","guid":{"rendered":"https:\/\/nubisoft.io\/blog\/?p=947"},"modified":"2022-10-03T11:42:58","modified_gmt":"2022-10-03T09:42:58","slug":"how-to-start-with-graphql-in-java","status":"publish","type":"post","link":"https:\/\/nubisoft.io\/blog\/how-to-start-with-graphql-in-java\/","title":{"rendered":"How to start with GraphQL in Java"},"content":{"rendered":"\n<p>In this blog post, you will learn some basics about <strong>GraphQL<\/strong> and how to start using it in an actual project with <strong>Java<\/strong> language and <strong>Spring Boot<\/strong> technology.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is GraphQL?<\/h2>\n\n\n\n<p>GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. The main concept of GraphQL is strong typing which determines the way of communication between the client and server. GraphQL&#8217;s main feature is its flexibility, which can be determined on the basis of two phenomena that very often occurs when using REST architecture &#8211; data over and under-fetching. <\/p>\n\n\n\n<p>Data Under-Fetching is a phenomenon that occurs when there is fewer data in response than the requester needs. This situation forces the client or other microservice to shoot the server whit another request to get the missing data. <\/p>\n\n\n\n<p>Data Over-Fetching is a phenomenon that occurs when there is more data in response than the client or other microservice uses.<\/p>\n\n\n\n<p>In both cases, there are performance issues that cause problems. In the first case, the client is forced to make additional HTTP requests when it should send only a single request in the ideal situation. In the second case, there is more usage of bandwidth than it could be, as the client is not using all the data that was received, which also slows down the application. <\/p>\n\n\n\n<p>Against these problems, there is the GraphQL language, which thanks to the above-mentioned flexibility, i.e. the possibility of sending many queries within one request and the possibility of selecting the required fields within each request eliminates these two phenomena such as data under and over-fetching.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Basics of GraphQL<\/h2>\n\n\n\n<p>In GraphQL to create an API, it is necessary to create schemas that will define possible queries including what this query will return and what are the required parameters. There are two main concepts for operating on the data: <em>Queries<\/em> and <em>Mutations<\/em>. <\/p>\n\n\n\n<p><em>Query<\/em> in GraphQL is a substitute for HTTP GET in REST architecture and it&#8217;s used only to get data from the server. <\/p>\n\n\n\n<p><em>Mutation<\/em> is a substitute for HTTP POST\/PUT\/DELETE which is used to operate on data especially by sending new data to the server, updating already existing data, or deleting it from the server.<\/p>\n\n\n\n<p>In each of the GraphQL operations, we have some keywords that allow defining schemas: <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><em>type<\/em> &#8211;  represent a kind of object that it&#8217;s possible to fetch from service, and what fields it has. This keyword is allowed to use only in <em>Queries<\/em>.<\/li><li><em>input<\/em> &#8211; represents a kind of object that will make some changes in the server, allowed to use only in <em>Mutations<\/em>.<\/li><li><em>interface<\/em> &#8211; the abstract type that includes a certain set of fields that a type must include in implementing the interface.<\/li><li><em>enum<\/em> &#8211; enumeration types are a special kind of scalar that is restricted to a particular set of allowed values.<\/li><li><em>union<\/em> &#8211; very similar to interfaces, but they don&#8217;t get to specify any common fields between the types.<\/li><\/ul>\n\n\n\n<p>When defining schemas there are some predefined types like in other languages: Float, String, Boolean, Int, and new type ID which is a scalar type that represents some unique identifier. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enough theory, let&#8217;s start with some practical stuff such as integrating GraphQL with Spring Boot.<\/h2>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"315\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/spring-boot-logo-1.png\" alt=\"Spring Boot logo\" class=\"wp-image-957\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/spring-boot-logo-1.png 600w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/spring-boot-logo-1-300x158.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/figure><\/div>\n\n\n\n<p>To start it is recommended to use <a rel=\"noreferrer noopener\" href=\"https:\/\/start.spring.io\/\" target=\"_blank\">https:\/\/start.spring.io\/<\/a> to initialize your project. There are some necessary requirements to do. The <strong>Spring Boot<\/strong> version must be greater or equal to <strong>2.7.0<\/strong> and at least two packages must be included: <strong>Spring Web<\/strong> and <strong>Spring for GraphQL<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"571\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-1-1024x571.png\" alt=\"Spring Starter for new GraphQL project\" class=\"wp-image-959\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-1-1024x571.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-1-300x167.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-1-768x428.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-1-1200x669.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-1.png 1519w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Spring Starter for the new GraphQL project<\/figcaption><\/figure><\/div>\n\n\n\n<p>After successfully initializing your project if you are using IntelliJ it is also recommended to install a GraphQL plugin that will help with some stuff while coding.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"555\" height=\"374\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-2.png\" alt=\"GraphQL plugin for IntelliJ\" class=\"wp-image-961\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-2.png 555w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-2-300x202.png 300w\" sizes=\"auto, (max-width: 555px) 100vw, 555px\" \/><figcaption>GraphQL plugin for IntelliJ<\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Defining GraphQL schemas for our project<\/h2>\n\n\n\n<p>The scope of the project that we want to create for this lesson is to allow users to fetch all products and their details, and also filter products by price. There should be also some part of the functionality for admin users which includes adding, updating, and deleting products. In the first step of creating an API in the <code>resources<\/code> folder, we must create <code>graphql<\/code> folder which is the default path where schemas with <code>.graphqls<\/code> extension will be searched by the GraphQL library. Schemas could be separated into as many files as you want which is very helpful, especially in larger projects. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"267\" height=\"133\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-5.png\" alt=\"GparhQL schemas folder structure.\" class=\"wp-image-967\"\/><figcaption>GparhQL schemas folder structure<\/figcaption><\/figure><\/div>\n\n\n\n<p>As shown in the above image I recommend creating a main schema file called<code> schema.graphqls<\/code> in which we will define available <em>Queries<\/em> and <em>Mutations<\/em> and also create a package for each domain (in this case only products) which will be separated into two schemas &#8211; one for <em>Mutation<\/em> inputs and one for <em>Query<\/em> types.<\/p>\n\n\n\n<p>Let&#8217;s start with defining types for <em>Query<\/em> operations in the domain of the product: <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"383\" height=\"1024\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38-383x1024.png\" alt=\"GraphQL schema for Product.\" class=\"wp-image-1014\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38-383x1024.png 383w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38-112x300.png 112w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38-768x2056.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38-574x1536.png 574w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38-765x2048.png 765w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-38.png 1052w\" sizes=\"auto, (max-width: 383px) 100vw, 383px\" \/><figcaption>GraphQL schema for Product<\/figcaption><\/figure><\/div>\n\n\n\n<p>As you can see the type of Product consists of a unique id, name, price, and available types which consist of enums such as sex, color, and size of the product. Here you can also see two operators &#8211; <code>!<\/code> and <code>[]<\/code>, the first one informs us about the fact that this field can&#8217;t be <code>null<\/code>, and if it is, the server will respond with an error message. The second operator is used to define lists like in most programming languages. In that schema, <code>availableTypes<\/code> can be <code>null<\/code>, but because of <code>!<\/code> after <code>ProductType<\/code>, elements inside the list of the available types will never be <code>null<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"235\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39-1024x235.png\" alt=\"GraphQL Queries for Products\" class=\"wp-image-1015\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39-1024x235.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39-300x69.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39-768x176.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39-1536x352.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39-1200x275.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-39.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>GraphQL Queries for Products<\/figcaption><\/figure>\n\n\n\n<p>As we have defined our types for the Products domain there is a time to define available <em>Query<\/em> operations. It&#8217;s worth remembering that in all schema files <em>Query<\/em> type must be defined only in one place. <\/p>\n\n\n\n<p>Our available <em>Query<\/em> operations are <code>products<\/code> which will return a not nullable list of <code>Product<\/code> types with elements that also will never be <code>null<\/code>, <code>product<\/code> which takes <code>not null<\/code> unique id as a parameter and returns <code>Product<\/code> type, and the last one <code>productsByPrice<\/code> which takes two parameters <code>priceFrom<\/code> and <code>priceTo<\/code> which can be nullable, this operation will return a list of <code>Product<\/code> type.<\/p>\n\n\n\n<p>After creating part of our schema we can move this to our Java implementation, by converting defined schema types to Java classes. If you won&#8217;t change any field after creating objects it is recommended to use records as it takes less code.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"801\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-1024x801.png\" alt=\"Java class for Product. \" class=\"wp-image-1011\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-1024x801.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-300x235.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-768x601.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-1536x1201.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-2048x1602.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-1200x938.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-35-1980x1548.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"39\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-1024x39.png\" alt=\"Java Record for ProductType type.\" class=\"wp-image-1013\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-1024x39.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-300x12.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-768x29.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-1536x59.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-2048x79.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-1200x46.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-37-1980x76.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"270\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-46-1024x270.png\" alt=\"Java enum for ColorType type.\" class=\"wp-image-1023\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-46-1024x270.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-46-300x79.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-46-768x203.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-46-1200x317.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-46.png 1250w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>After moving schemas to classes we can start with implementing a <em>Controller<\/em> for our products domain.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"604\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-1024x604.png\" alt=\"Spring Boot Controller class for GraphQL API\" class=\"wp-image-1010\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-1024x604.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-300x177.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-768x453.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-1536x906.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-2048x1207.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-1200x707.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-34-1980x1167.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Spring Boot Controller class for GraphQL API<\/figcaption><\/figure>\n\n\n\n<p>To create our <em>Controller<\/em> we need to annotate it with <code>@Controller<\/code> annotation from <code>org.springframework.stereotype<\/code> package. To handle our schema <em>Query<\/em> operations we have two possibilities. The first one is by using <code>@SchemaMapping<\/code> annotation in which we don&#8217;t have to be consistent in naming of methods and their corresponding schema operation, but it is necessary to pass at least two arguments to this annotation: <code>typeName<\/code> &#8211; in our case Query tells what kind of operation it is &#8211; and the value which should be the name of the schema operation. The second option is to use <code>@QueryMapping<\/code> annotation which under the hood is the former one but it binds schema operation with this method by its name, so it is necessary in that case to be consistent in the naming of methods and schema operations. <\/p>\n\n\n\n<p>To take request parameters there is also <code>@Argument<\/code> annotation that maps fields into required types by name of the parameter.<\/p>\n\n\n\n<p>Let&#8217;s move to define <em>Mutations<\/em> in the domain of the products. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"849\" height=\"1024\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-40-849x1024.png\" alt=\"GraphQL mutations for Product\" class=\"wp-image-1016\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-40-849x1024.png 849w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-40-249x300.png 249w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-40-768x927.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-40-1200x1448.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-40.png 1240w\" sizes=\"auto, (max-width: 849px) 100vw, 849px\" \/><figcaption>GraphQL mutations types for Product<\/figcaption><\/figure><\/div>\n\n\n\n<p>As mentioned above to define mutation types it is necessary to use the <code>input<\/code> keyword, types cannot be used here, but enums can be used between these two operations. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"323\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41-1024x323.png\" alt=\"\" class=\"wp-image-1017\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41-1024x323.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41-300x95.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41-768x243.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41-1536x485.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41-1200x379.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-41.png 1672w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>GraphQL mutation for Product<\/figcaption><\/figure><\/div>\n\n\n\n<p>As we have defined our inputs for the Products domain there is a time to define available <em>Mutation<\/em> operations. It&#8217;s worth remembering that in all schema files <em>Mutation<\/em>, like <em>Query<\/em> type must be defined only in one place and all <em>Mutation<\/em> operations should return something. <\/p>\n\n\n\n<p>Our available <em>Mutation<\/em> type operations are <code>createProducts<\/code> which takes as parameter <code>CreateProductMutation<\/code> input, <code>updateProduct<\/code> which takes as parameter <code>UpdateProductMutation<\/code>, and <code>deleteProduct<\/code> which takes as a parameter the unique ID of the product to be deleted. All of these mutations return the unique ID of the product on which they operate.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"121\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-1024x121.png\" alt=\"\" class=\"wp-image-1018\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-1024x121.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-300x35.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-768x91.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-1536x182.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-2048x242.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-1200x142.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-42-1980x234.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"74\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-1024x74.png\" alt=\"\" class=\"wp-image-1019\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-1024x74.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-300x22.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-768x55.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-1536x110.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-2048x147.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-1200x86.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-43-1980x142.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"37\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-1024x37.png\" alt=\"\" class=\"wp-image-1020\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-1024x37.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-300x11.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-768x28.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-1536x56.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-2048x75.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-1200x44.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-44-1980x72.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Again we moved schema inputs to the Java records, as mutations will not be changed. After that, we can add the handling of defined mutations in our ProductsController.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"633\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-1024x633.png\" alt=\"\" class=\"wp-image-1021\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-1024x633.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-300x185.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-768x475.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-1536x949.png 1536w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-2048x1266.png 2048w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-1200x742.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-45-1980x1224.png 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Controller methods for handling mutation requests<\/figcaption><\/figure><\/div>\n\n\n\n<p>To handle our <em>Mutation<\/em> schema operations there is a specified annotation <code>@MutatuionMapping<\/code> which  <code>QueryMapping<\/code> is under the hood <code>@SchemaMapping<\/code>. This annotation also requires to be consistent with operations defined inside schemas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing API with GraphiQL<\/h2>\n\n\n\n<p>To test created API we can use Postman or another tool but the GraphQL library for Spring Boot has a built-in extension called GraphiQL to make it easier for developers. <\/p>\n\n\n\n<p>To enable this extension it is necessary to add an entry in the application.properties file which is: <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">spring.graphql.graphiql.enabled=true\nserver.port=9000<\/pre>\n\n\n\n<p>After adding this entry and running our application the GraphiQL should be available at <a rel=\"noreferrer noopener\" href=\"http:\/\/localhost:9000\/graphiql?path=\/graphql\" target=\"_blank\">http:\/\/localhost:9000\/graphiql?path=\/graphql<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"548\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-1024x548.png\" alt=\"GraphiQL user interface\" class=\"wp-image-1035\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-1024x548.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-300x161.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-768x411.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image.png 1119w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>GraphiQL user interface<\/figcaption><\/figure>\n\n\n\n<p>GraphiQL is the GraphQL integrated development environment that allows sending requests to the API. It contains built-in documentation which can be displayed by clicking the button on the left side of the window. Documentation is available by prefetching defined schemas, which allows for checking all possible operations, types and their explanations. It also provides suggestions when writing GraphQL requests, or the history of our requests.<\/p>\n\n\n\n<p>By default, types defined in schemas have no description, but by adding <code># description<\/code> above the type or field, we can add it to the documentation in GraphiQL, which can be useful in more complex types or business aspects.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"762\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-47-1024x762.png\" alt=\"\" class=\"wp-image-1025\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-47-1024x762.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-47-300x223.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-47-768x572.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-47-1200x894.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/08\/image-47.png 1300w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>GraphQL type with documentation for GraphiQL extension<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"542\" height=\"536\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-1.png\" alt=\"\" class=\"wp-image-1036\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-1.png 542w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-1-300x297.png 300w\" sizes=\"auto, (max-width: 542px) 100vw, 542px\" \/><figcaption>GraphQL type documentation shown in the GraphiQL user interface<\/figcaption><\/figure>\n\n\n\n<p>Let&#8217;s make our first Query request with GraphQL: <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"547\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-2-1024x547.png\" alt=\"\" class=\"wp-image-1037\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-2-1024x547.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-2-300x160.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-2-768x410.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-2.png 1120w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>To send a <em>Query<\/em> to the server it should be wrapped inside the <code>query<\/code> keyword, after that by clicking ctrl + space, GraphiQL will suggest available operations to perform. As you can see in the products operation, we specify that we want only IDs and sizes of available types in the response; that is exactly what the server returns. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"549\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-3-1024x549.png\" alt=\"GraphQL request and response\" class=\"wp-image-1038\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-3-1024x549.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-3-300x161.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-3-768x411.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-3.png 1122w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>GraphQL request and response<\/figcaption><\/figure>\n\n\n\n<p>Here we can see the mentioned above flexibility of GraphiQL. The developer fully controls which fields will appear in the response, by adding their names based on the defined schemas. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"518\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-4-1024x518.png\" alt=\"Example of multiple Queries send with one request\" class=\"wp-image-1039\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-4-1024x518.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-4-300x152.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-4-768x389.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-4.png 1162w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Example of multiple Queries sent with one request<\/figcaption><\/figure>\n\n\n\n<p>In this example, we are executing three operations with one query, which results in one response with all required data &#8211; details of products with id 5, products with a price between 10 and 30, and also all products.<\/p>\n\n\n\n<p>Let&#8217;s move to our first mutation request: <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"458\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-5-1024x458.png\" alt=\"Example of mutation request\" class=\"wp-image-1040\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-5-1024x458.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-5-300x134.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-5-768x343.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-5-1200x536.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-5.png 1255w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Example of mutation request<\/figcaption><\/figure>\n\n\n\n<p>As it was for <em>Queries<\/em>, to specify our first <em>Mutation<\/em> all requests should be contained in the <code>mutation<\/code> keyword. As you can see in this example we are using the <code>variables<\/code> field, which in our situation is not relevant, but in real applications, it&#8217;s where actual data will be &#8211; we shouldn&#8217;t manipulate Query directly but only by the variables passed to it. In server response, we got the id of the created product so we can check if everything was saved correctly by fetching the product by its id:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"416\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-6-1024x416.png\" alt=\"\" class=\"wp-image-1041\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-6-1024x416.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-6-300x122.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-6-768x312.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-6-1200x488.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-6.png 1304w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>As you can see the product was saved correctly with all data passed as variables. Now we can try to update our product: <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"402\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-7-1024x402.png\" alt=\"Mutation request to update a Product\" class=\"wp-image-1042\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-7-1024x402.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-7-300x118.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-7-768x302.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-7-1200x471.png 1200w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-7.png 1214w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In this situation, we are also using variables to have a more generic way of sending update mutation requests. Lets again fetch our product to see that everything was updated as expected:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"407\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-8-1024x407.png\" alt=\"Query to get Product by ID\" class=\"wp-image-1043\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-8-1024x407.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-8-300x119.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-8-768x305.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-8.png 1133w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>As you can see on the right side, the product was updated successfully. At the end of our journey we can try to delete a product that we created: <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"363\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-9-1024x363.png\" alt=\"Mutation for deleting Product  \" class=\"wp-image-1048\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-9-1024x363.png 1024w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-9-300x106.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-9-768x272.png 768w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-9.png 1062w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Let&#8217;s check what products are left in the system and ensure that the product with id 6 was removed:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"811\" height=\"673\" src=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-10.png\" alt=\"GraphQL Query to fetch all Products. \" class=\"wp-image-1049\" srcset=\"https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-10.png 811w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-10-300x249.png 300w, https:\/\/nubisoft.io\/blog\/wp-content\/uploads\/2022\/10\/image-10-768x637.png 768w\" sizes=\"auto, (max-width: 811px) 100vw, 811px\" \/><\/figure>\n\n\n\n<p>As you can see there is no product with id 6, so we can say that product was deleted successfully.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>GraphQL is growing rapidly and it is used in many production applications by companies of any size. It could become a ubiquitous technology for API in the upcoming years, but of course, it has good and bad sides. GraphQL is very flexible and allows to prevent two common phenomena observed in REST architecture such as data over and under fetching, by allowing to request only required fields and perform more than one query or mutation at once. One of the main problems of GraphQL is the &#8220;N+1 Problem&#8221; which occurs when GraphQL resolvers issue one query to the underlying data source along with N number of subsequent queries to fetch.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post, you will learn some basics about GraphQL and how to start using it in an actual project with Java language and Spring Boot technology. What is GraphQL? GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. The main concept of GraphQL is [&hellip;]<\/p>\n","protected":false},"author":9,"featured_media":949,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_case_study_excerpt":"","footnotes":""},"categories":[3,45],"tags":[249,248],"class_list":["post-947","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-development","category-system-architecture","tag-api","tag-graphql"],"_links":{"self":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts\/947","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/comments?post=947"}],"version-history":[{"count":42,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts\/947\/revisions"}],"predecessor-version":[{"id":1150,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/posts\/947\/revisions\/1150"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/media\/949"}],"wp:attachment":[{"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/media?parent=947"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/categories?post=947"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nubisoft.io\/blog\/wp-json\/wp\/v2\/tags?post=947"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}