<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kotlin coroutines Archives - Codersee blog- Kotlin on the backend</title>
	<atom:link href="https://blog.codersee.com/tag/kotlin-coroutines/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>Kotlin &#38; Backend Tutorials - Learn Through Practice.</description>
	<lastBuildDate>Thu, 17 Apr 2025 09:17:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.codersee.com/wp-content/uploads/2025/04/cropped-codersee_logo_circle_2-32x32.png</url>
	<title>Kotlin coroutines Archives - Codersee blog- Kotlin on the backend</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Spring for GraphQL with Kotlin Coroutines</title>
		<link>https://blog.codersee.com/spring-graphql-kotlin-coroutines/</link>
					<comments>https://blog.codersee.com/spring-graphql-kotlin-coroutines/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Sat, 12 Apr 2025 12:10:34 +0000</pubDate>
				<category><![CDATA[Spring]]></category>
		<category><![CDATA[GraphQL]]></category>
		<category><![CDATA[Kotlin coroutines]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=19012915</guid>

					<description><![CDATA[<p>In this tutorial, we will learn how to expose GraphQL APIs using Spring for GraphQL and Kotlin coroutines.</p>
<p>The post <a href="https://blog.codersee.com/spring-graphql-kotlin-coroutines/">Spring for GraphQL with Kotlin Coroutines</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>At the end of this article, you will know precisely how to create a <strong>Spring Boot GraphQL</strong> application that exposes <strong>queries</strong> and <strong>mutations</strong> with the help of Kotlin <strong>suspended functions</strong> and <strong>Flows</strong>. </p>



<p>Long story short, we will see: </p>



<ul class="wp-block-list">
<li>how to prepare a GraphQL schema,</li>



<li>what imports are necessary to utilize suspended functions,</li>



<li>how to expose queries, mutations, and map schema with annotated controllers,</li>



<li>exception handling with <code>GraphQlExceptionHandler</code> </li>
</ul>



<h2 class="wp-block-heading" id="h-create-project">Create Project </h2>



<p>As the first step, let&#8217;s prepare a brand new project. </p>



<p>To do so, let&#8217;s navigate to the <a href="https://start.spring.io/" target="_blank" rel="noreferrer noopener">Spring Initializr</a> page and select the following imports: </p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="537" src="http://blog.codersee.com/wp-content/uploads/2025/04/spring_for_graphql_webflux_spring_initializr_page_screenshot-1024x537.png" alt="Image is a screenshot from Spring Initializr page and shows necessary spring configs for the tutorial, among others, Spring Reactive Web and Spring for GraphQL" class="wp-image-19012919" srcset="https://blog.codersee.com/wp-content/uploads/2025/04/spring_for_graphql_webflux_spring_initializr_page_screenshot-1024x537.png 1024w, https://blog.codersee.com/wp-content/uploads/2025/04/spring_for_graphql_webflux_spring_initializr_page_screenshot-300x157.png 300w, https://blog.codersee.com/wp-content/uploads/2025/04/spring_for_graphql_webflux_spring_initializr_page_screenshot-768x403.png 768w, https://blog.codersee.com/wp-content/uploads/2025/04/spring_for_graphql_webflux_spring_initializr_page_screenshot.png 1530w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>The project <strong>metadata</strong> are totally up to you, but when it comes to the <strong>dependencies</strong>, we must select the <em>Spring Reactive Web</em> and <em>Spring for GraphQL</em>.</p>



<p>Thanks to the first one, Spring Boot configures a <strong>reactive web stack</strong> based on <strong>Project Reactor</strong> and <strong>Netty</strong> instead of Tomcat. And given we want to work with GraphQL <strong>and </strong>Kotlin coroutines, then this is a must-have for us. </p>



<p>The second provides support for Spring applications built on GraphQL Java. Moreover, it is the <strong>successor</strong> of the GraphQL Java Spring project from the GraphQL Java team.</p>



<p>Lastly, let&#8217;s download the zip package, extract and import it to our IDE. </p>



<h2 class="wp-block-heading" id="h-define-graphql-schema">Define GraphQL Schema</h2>



<h3 class="wp-block-heading" id="h-what-is-graphql-schema">What is GraphQL Schema?</h3>



<p>If you have ever worked with GraphQL before, then you know that compared to the REST, everything starts with <strong>schema definition</strong>.</p>



<p>If you haven&#8217;t, then <strong>GraphQL schema</strong> is a file typically written with <strong>Schema Definition Language (SDL)</strong> that describes how our API clients can interact with our server. To be more specific, inside it, we define the structure of returned data, as well as how consumers can fetch or send us the payloads. </p>



<p>And even though it may sound like a GraphQL substitute for OpenAPI specs, it is something more. In REST, OpenAPI docs are a nice addition to our project. In GraphQL, our services continuously utilize the schema definition to validate and execute requests against it. </p>



<p>And if you would like to learn more about GraphQL schema, then check out the <a href="https://graphql.org/learn/schema/">official documentation</a> later. But for now, let&#8217;s focus on the Spring / GraphQL / Kotlin combination 😉 </p>



<h3 class="wp-block-heading" id="h-schema-graphql-in-spring">schema.graphql in Spring </h3>



<p>As the first step, let&#8217;s head to the <code>resources &gt; graphql</code> directory in our project, and let&#8217;s insert the <code>schema.graphql</code> file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="type Query {
  article(id: ID!): Article
  articles: [Article!]!
}

type Mutation {
  createArticle(input: CreateArticleInput!): Article!
  addComment(articleId: ID!, input: AddCommentInput!): Comment
}

input CreateArticleInput {
  title: String!
  content: String!
  userId: ID!
}

input AddCommentInput {
  userId: String!
  content: String!
}

type User {
  id: ID!
  name: String!
}

type Article {
  id: ID!
  title: String!
  content: String!
  author: User!
  comments: [Comment!]!
  createdAt: String!
}

type Comment {
  id: ID!
  content: String!
  author: User
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">type</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Query</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  article(id: ID!): Article</span></span>
<span class="line"><span style="color: #E1E4E8">  articles: [Article!]!</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">type</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Mutation</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  createArticle(input: CreateArticleInput!): Article!</span></span>
<span class="line"><span style="color: #E1E4E8">  addComment(articleId: ID!, input: AddCommentInput!): Comment</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">input CreateArticleInput {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">title</span><span style="color: #E1E4E8">: String</span><span style="color: #F97583">!</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">content</span><span style="color: #E1E4E8">: String</span><span style="color: #F97583">!</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">userId</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">ID</span><span style="color: #F97583">!</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">input AddCommentInput {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">userId</span><span style="color: #E1E4E8">: String</span><span style="color: #F97583">!</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">content</span><span style="color: #E1E4E8">: String</span><span style="color: #F97583">!</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">type</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  id: ID!</span></span>
<span class="line"><span style="color: #E1E4E8">  name: String!</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">type</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  id: ID!</span></span>
<span class="line"><span style="color: #E1E4E8">  title: String!</span></span>
<span class="line"><span style="color: #E1E4E8">  content: String!</span></span>
<span class="line"><span style="color: #E1E4E8">  author: User!</span></span>
<span class="line"><span style="color: #E1E4E8">  comments: [Comment!]!</span></span>
<span class="line"><span style="color: #E1E4E8">  createdAt: String!</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">type</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  id: ID!</span></span>
<span class="line"><span style="color: #E1E4E8">  content: String!</span></span>
<span class="line"><span style="color: #E1E4E8">  author: User</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>In Spring Boot, this file is registered automatically as our schema definition. </p>



<p>And as we can see, we defined 5 things: </p>



<ul class="wp-block-list">
<li><strong>queries</strong>&#8211; how a client reads data. Every GraphQL schema <strong>must </strong>support them,</li>



<li><strong>mutations</strong>&#8211; how a client modifies data,     </li>



<li><strong>inputs</strong>&#8211; used to pass structured arguments to our mutations and queries,</li>



<li><strong>types</strong>&#8211; establishing the structure of data we return,</li>



<li><strong>scalars</strong>&#8211; like <code>String</code>, or <code>ID</code> (but also <code>Int</code>, <code>Float</code>, <code>Boolean</code>), describing returned fields.</li>
</ul>



<p>Moreover, we can see the exclamation mark- <code>!</code>. In contrast to Kotlin, in GraphQL, we must <strong>explicitly define non-nullable types.</strong> Meaning, that <code>[Comment]</code> describes a nullable array of nullable <code>Comment</code> type (<code>Array&lt;Comment?&gt;?</code>), whereas <code>[Comment!]!</code> is a not null array with not null items.</p>



<h3 class="wp-block-heading" id="h-spring-graphql-schema-inspection">Spring GraphQL Schema Inspection</h3>



<p>Following, let&#8217;s rerun our application. </p>



<p>As a result, we should get the following in logs: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="o.s.b.a.g.GraphQlAutoConfiguration: GraphQL schema inspection:
Unmapped fields: {Query=[article, articles], Mutation=[createArticle, addComment]}
Unmapped registrations: {}
Unmapped arguments: {}
Skipped types: []" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #d8dee9ff">o.s.b.a.g.GraphQlAutoConfiguration: GraphQL schema inspection:</span></span>
<span class="line"><span style="color: #d8dee9ff">Unmapped fields: {Query=[article, articles], Mutation=[createArticle, addComment]}</span></span>
<span class="line"><span style="color: #d8dee9ff">Unmapped registrations: {}</span></span>
<span class="line"><span style="color: #d8dee9ff">Unmapped arguments: {}</span></span>
<span class="line"><span style="color: #d8dee9ff">Skipped types: []</span></span></code></pre></div>



<p>As we can see, Spring Boot verifies the schema we defined every time we start the application. And the above message simply says that <strong>we do not have handler methods for our definition.</strong></p>



<p>Let&#8217;s fix that then 😉</p>



<h2 class="wp-block-heading" id="h-create-models">Create Models </h2>



<p>As the next step, let&#8217;s add Kotlin data classes to our Spring Boot project. They will be later used to serialize and deserialize data defined in our GraphQL schema.</p>



<p>To do so, let&#8217;s add the <code>Models.kt</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="data class User(
    val id: String,
    val name: String,
)
data class Article(
    val id: String,
    val title: String,
    val content: String,
    val authorId: String,
    val createdAt: String,
)
data class Comment(
    val id: String,
    val content: String,
    val articleId: String,
    val userId: String,
)
data class CreateArticleInput(
    val title: String,
    val content: String,
    val userId: String,
)
data class AddCommentInput(
    val content: String,
    val userId: String,
)" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">data</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> name: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #F97583">data</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> title: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> content: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> authorId: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> createdAt: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #F97583">data</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> content: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> articleId: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> userId: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #F97583">data</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">CreateArticleInput</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> title: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> content: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> userId: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #F97583">data</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">AddCommentInput</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> content: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> userId: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">)</span></span></code></pre></div>



<p>As we can see, nothing spectacular here. The only interesting fact is that the <code>ID</code> is serialized in the same way as a <code>String</code>.</p>



<h2 class="wp-block-heading" id="h-querymapping-as-suspend-fun">QueryMapping as suspend fun</h2>



<p>Following, let&#8217;s learn how the Spring for GraphQL works with Kotlin coroutines. </p>



<p>According to the documentation:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Kotlin coroutine and <code>Flow</code> are adapted to <code>Mono</code> and <code>Flux</code>.</p>
</blockquote>



<p>Which means that whenever we use the Spring WebFlux, <strong>Spring automatically converts our suspended functions <code>Mono</code> and functions that return <code>Flow</code> to <code>Flux</code></strong> .</p>



<h3 class="wp-block-heading" id="h-implement-article-service">Implement Article Service</h3>



<p>Before we head to the GraphQL part, let&#8217;s make some small preparations.</p>



<p>Let&#8217;s insert the <code>ArticleService</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@Component
object ArticleService {
    private val articles = mutableListOf(
        Article(
            id = &quot;article-id-1&quot;,
            title = &quot;article-title-1&quot;,
            content = &quot;article-content-1&quot;,
            authorId = &quot;user-id-2&quot;,
            createdAt = LocalDateTime.now().toString()
        ),
        Article(
            id = &quot;article-id-2&quot;,
            title = &quot;article-title-2&quot;,
            content = &quot;article-content-2&quot;,
            authorId = &quot;user-id-2&quot;,
            createdAt = LocalDateTime.now().toString()
        ),
        Article(
            id = &quot;article-id-3&quot;,
            title = &quot;article-title-3&quot;,
            content = &quot;article-content-3&quot;,
            authorId = &quot;user-id-3&quot;,
            createdAt = LocalDateTime.now().toString()
        ),
    )
    suspend fun findArticleById(id: String): Article? {
        delay(100)
        return articles.firstOrNull { it.id == id }
    }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@Component</span></span>
<span class="line"><span style="color: #F97583">object</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">ArticleService</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">private</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> articles </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">mutableListOf</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-title-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-content-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">        ),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-title-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-content-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">        ),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-title-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-content-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">        ),</span></span>
<span class="line"><span style="color: #E1E4E8">    )</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">findArticleById</span><span style="color: #E1E4E8">(id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">? {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">delay</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">100</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> articles.</span><span style="color: #B392F0">firstOrNull</span><span style="color: #E1E4E8"> { it.id </span><span style="color: #F97583">==</span><span style="color: #E1E4E8"> id }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As we can see, we use my favorite, in-memory database called <strong>mutable list</strong> (😉) and expose <code>findArticleById</code> &#8211; a suspended function.</p>



<p>This function will either find the desired article by ID or return a null value.</p>



<h3 class="wp-block-heading" id="h-add-articlecontroller">Add ArticleController</h3>



<p>With that done, let&#8217;s add the <code>ArticleController</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@Controller
class ArticleController(
    private val articleService: ArticleService,
) {
    @QueryMapping
    suspend fun article(@Argument id: String): Article? =
        articleService.findArticleById(id)
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@Controller</span></span>
<span class="line"><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">ArticleController</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">private</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> articleService: </span><span style="color: #B392F0">ArticleService</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #B392F0">@QueryMapping</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">article</span><span style="color: #E1E4E8">(</span><span style="color: #B392F0">@Argument</span><span style="color: #E1E4E8"> id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">? </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">        articleService.</span><span style="color: #B392F0">findArticleById</span><span style="color: #E1E4E8">(id)</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As we can see, thanks to the Spring GraphQL, we can leverage the annotation-based approach.</p>



<p>Firstly, we must annotate our class with the <strong>@Controller </strong>annotation. Then, all the methods inside it annotated with <strong>@SchemaMapping</strong> annotation will become handlers. </p>



<p>And <strong>@QueryMapping, @MutationMapping, </strong>or <strong>@SubscriptionMapping</strong> are nothing else than meta annotations (annotated with @SchemaMapping). This way, we achieve a more readable code. </p>



<p>Additionally, in Spring, we use the <code><strong>@Argument</strong></code> annotation to bind GraphQL input arguments to our Kotlin instances. </p>



<h3 class="wp-block-heading" id="h-enable-graphiql-amp-test">Enable GraphiQL &amp; Test</h3>



<p>Nextly, let&#8217;s turn on the <strong>GraphiQL</strong>&#8211; the IDE for testing GraphQL APIs (like Postman, Bruno, or Insomnia).</p>



<p>To do so, let&#8217;s navigate to the <code>resources</code> directory and change the <code>application.properties</code> into the <code>application.yaml</code> file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="spring:
  application:
    name: graphsandbox
  graphql:
    graphiql:
      enabled: true" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #85E89D">spring</span><span style="color: #E1E4E8">:</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #85E89D">application</span><span style="color: #E1E4E8">:</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #85E89D">name</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">graphsandbox</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #85E89D">graphql</span><span style="color: #E1E4E8">:</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #85E89D">graphiql</span><span style="color: #E1E4E8">:</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #85E89D">enabled</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">true</span></span></code></pre></div>



<p>Then, let&#8217;s open up the browser, go to <code>http://localhost:8080/graphiql</code>, and put the following: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="query SomeRandomQuery {
  article(id: &quot;article-id-1&quot;) {
    id
    title
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">query</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">SomeRandomQuery</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #FFAB70">article</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">id</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">title</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As we can see, the <strong>query</strong> name is up to us, but inside it, we must define which of the &#8220;exposed&#8221; queries we would like to use. As the input parameter, we pass the String value- <code>article-id-1</code>&#8211; and lastly, we define what fields we would like to get in response (that&#8217;s what the whole GraphQL is a about, right?😉).</p>



<p>So, as the next step, let&#8217;s run the query and check out the result: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;errors&quot;: [
    {
      &quot;message&quot;: &quot;INTERNAL_ERROR for f337f3f3-5&quot;,
      &quot;locations&quot;: [
        {
          &quot;line&quot;: 2,
          &quot;column&quot;: 3
        }
      ],
      &quot;path&quot;: [
        &quot;article&quot;
      ],
      &quot;extensions&quot;: {
        &quot;classification&quot;: &quot;INTERNAL_ERROR&quot;
      }
    }
  ],
  &quot;data&quot;: {
    &quot;article&quot;: null
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;errors&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">    {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;message&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;INTERNAL_ERROR for f337f3f3-5&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;locations&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">        {</span></span>
<span class="line"><span style="color: #E1E4E8">          </span><span style="color: #79B8FF">&quot;line&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">          </span><span style="color: #79B8FF">&quot;column&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">3</span></span>
<span class="line"><span style="color: #E1E4E8">        }</span></span>
<span class="line"><span style="color: #E1E4E8">      ],</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;path&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #9ECBFF">&quot;article&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      ],</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;extensions&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;classification&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;INTERNAL_ERROR&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  ],</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;article&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">null</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>Unfortunately, that is not what we expected. </p>



<p>Moreover, when we check out logs, we should see this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="s.g.e.ExceptionResolversExceptionHandler : Unresolved NoClassDefFoundError for executionId f337f3f3-5
java.lang.NoClassDefFoundError: org/springframework/data/util/KotlinReflectionUtils
	at org.springframework.graphql.data.method.InvocableHandlerMethodSupport.invokeSuspendingFunction(InvocableHandlerMethodSupport.java:141) ~[spring-graphql-1.3.4.jar:1.3.4]
	at org.springframework.graphql.data.method.InvocableHandlerMethodSupport.doInvoke(InvocableHandlerMethodSupport.java:108) ~[spring-graphql-1.3.4.jar:1.3.4]" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">s.g.e.ExceptionResolversExceptionHandler : Unresolved NoClassDefFoundError for executionId f337f3f3-5</span></span>
<span class="line"><span style="color: #e1e4e8">java.lang.NoClassDefFoundError: org/springframework/data/util/KotlinReflectionUtils</span></span>
<span class="line"><span style="color: #e1e4e8">	at org.springframework.graphql.data.method.InvocableHandlerMethodSupport.invokeSuspendingFunction(InvocableHandlerMethodSupport.java:141) ~[spring-graphql-1.3.4.jar:1.3.4]</span></span>
<span class="line"><span style="color: #e1e4e8">	at org.springframework.graphql.data.method.InvocableHandlerMethodSupport.doInvoke(InvocableHandlerMethodSupport.java:108) ~[spring-graphql-1.3.4.jar:1.3.4]</span></span></code></pre></div>



<h3 class="wp-block-heading" id="h-fix-spring-graphql-coroutines-issue">Fix Spring GraphQL Coroutines Issue</h3>



<p>As we could see, the issue is caused by the missing dependency, and we can easily fix that.</p>



<p>To do so, let&#8217;s open up the <code>build.gradle.kts</code> and add the following dependency:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="implementation(&quot;org.springframework.data:spring-data-commons&quot;)" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">implementation(&quot;org.springframework.data:spring-data-commons&quot;)</span></span></code></pre></div>



<p>Then, let&#8217;s sync the gradle project and rerun the application.</p>



<p>After we run the test again, we should see the following:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;data&quot;: {
    &quot;article&quot;: {
      &quot;id&quot;: &quot;article-id-1&quot;,
      &quot;title&quot;: &quot;article-title-1&quot;
    }
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;article&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;title&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-title-1&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>Splendid! Everything works perfectly fine😉</p>



<h2 class="wp-block-heading" id="h-spring-graphql-with-kotlin-flow">Spring GraphQL with Kotlin Flow </h2>



<p>With that done, let&#8217;s learn how to work with Kotlin Flow and Spring GraphQL.</p>



<p>As the first step, let&#8217;s insert a new function to our <code>ArticleService</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="fun findAllArticles(): Flow&lt;Article&gt; = articles.asFlow()" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">findAllArticles</span><span style="color: #E1E4E8">(): </span><span style="color: #B392F0">Flow</span><span style="color: #E1E4E8">&lt;</span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">&gt; </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> articles.</span><span style="color: #B392F0">asFlow</span><span style="color: #E1E4E8">()</span></span></code></pre></div>



<p>This way, we produce a <strong>cold flow</strong> from our list of articles.</p>



<p>Then, let&#8217;s add a new handler:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@QueryMapping
fun articles(): Flow&lt;Article&gt; =
    articleService.findAllArticles()" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@QueryMapping</span></span>
<span class="line"><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">articles</span><span style="color: #E1E4E8">(): </span><span style="color: #B392F0">Flow</span><span style="color: #E1E4E8">&lt;</span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">&gt; </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">    articleService.</span><span style="color: #B392F0">findAllArticles</span><span style="color: #E1E4E8">()</span></span></code></pre></div>



<p>Nothing new this time. Just like previously, we add a new function marked with <strong>@QueryMapping</strong>.</p>



<p>When we run the following query in GraphiQL: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="query AnotherOne {
  articles {
    id
    title
    createdAt
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">query</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">AnotherOne</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #FFAB70">articles</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">title</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">createdAt</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>We should see the exact result: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;data&quot;: {
    &quot;articles&quot;: [
      {
        &quot;id&quot;: &quot;article-id-1&quot;,
        &quot;title&quot;: &quot;article-title-1&quot;,
        &quot;createdAt&quot;: &quot;2025-04-12T13:06:29.142469200&quot;
      },
      {
        &quot;id&quot;: &quot;article-id-2&quot;,
        &quot;title&quot;: &quot;article-title-2&quot;,
        &quot;createdAt&quot;: &quot;2025-04-12T13:06:29.142469200&quot;
      },
      {
        &quot;id&quot;: &quot;article-id-3&quot;,
        &quot;title&quot;: &quot;article-title-3&quot;,
        &quot;createdAt&quot;: &quot;2025-04-12T13:06:29.142469200&quot;
      }
    ]
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;articles&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">      {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;title&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-title-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;createdAt&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;2025-04-12T13:06:29.142469200&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      },</span></span>
<span class="line"><span style="color: #E1E4E8">      {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;title&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-title-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;createdAt&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;2025-04-12T13:06:29.142469200&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      },</span></span>
<span class="line"><span style="color: #E1E4E8">      {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-id-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;title&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-title-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;createdAt&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;2025-04-12T13:06:29.142469200&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #E1E4E8">    ]</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<h2 class="wp-block-heading" id="h-schemamapping">@SchemaMapping</h2>



<p>One of the greatest thing in GraphQL is the possibility to return the related data in one, single query. And if you remember our schema definition, our API should allow us to do that.</p>



<p>To be more specific, each article can have the <strong>author</strong>, multiple <strong>comments</strong>, and each comment also has its <strong>author</strong>.</p>



<p>But when we test that functionality right now:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="query AnotherOne {
  articles {
    id
    title
    createdAt
    author {
      id
      name
    }
    
    comments {
      id
      content
      author {
        name
      }
    }
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">query</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">AnotherOne</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #FFAB70">articles</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">title</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">createdAt</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">author</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">name</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">    </span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">comments</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">content</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">author</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #FFAB70">name</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>The only thing we will get in response will be a looooong list of errors:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;errors&quot;: [
    {
      &quot;message&quot;: &quot;The field at path '/articles[0]/author' was declared as a non null type, but the code involved in retrieving data has wrongly returned a null value.  The graphql specification requires that the parent field be set to null, or if that is non nullable that it bubble up null to its parent and so on. The non-nullable type is 'User' within parent type 'Article'&quot;,
      &quot;path&quot;: [
        &quot;articles&quot;,
        0,
        &quot;author&quot;
      ],
      &quot;extensions&quot;: {
        &quot;classification&quot;: &quot;NullValueInNonNullableField&quot;
      }
    }
... other errors" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #e1e4e8">{</span></span>
<span class="line"><span style="color: #e1e4e8">  &quot;errors&quot;: [</span></span>
<span class="line"><span style="color: #e1e4e8">    {</span></span>
<span class="line"><span style="color: #e1e4e8">      &quot;message&quot;: &quot;The field at path &#39;/articles[0]/author&#39; was declared as a non null type, but the code involved in retrieving data has wrongly returned a null value.  The graphql specification requires that the parent field be set to null, or if that is non nullable that it bubble up null to its parent and so on. The non-nullable type is &#39;User&#39; within parent type &#39;Article&#39;&quot;,</span></span>
<span class="line"><span style="color: #e1e4e8">      &quot;path&quot;: [</span></span>
<span class="line"><span style="color: #e1e4e8">        &quot;articles&quot;,</span></span>
<span class="line"><span style="color: #e1e4e8">        0,</span></span>
<span class="line"><span style="color: #e1e4e8">        &quot;author&quot;</span></span>
<span class="line"><span style="color: #e1e4e8">      ],</span></span>
<span class="line"><span style="color: #e1e4e8">      &quot;extensions&quot;: {</span></span>
<span class="line"><span style="color: #e1e4e8">        &quot;classification&quot;: &quot;NullValueInNonNullableField&quot;</span></span>
<span class="line"><span style="color: #e1e4e8">      }</span></span>
<span class="line"><span style="color: #e1e4e8">    }</span></span>
<span class="line"><span style="color: #e1e4e8">... other errors</span></span></code></pre></div>



<p>Of course, with Spring we can easily fix it, but we will need small preparation first.</p>



<h3 class="wp-block-heading" id="h-update-service">Update Service</h3>



<p>Firstly, let&#8217;s get back to our service and update it: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@Component
object ArticleService {
    private val articles = mutableListOf(
        Article(
            id = &quot;article-id-1&quot;,
            title = &quot;article-title-1&quot;,
            content = &quot;article-content-1&quot;,
            authorId = &quot;user-id-2&quot;,
            createdAt = LocalDateTime.now().toString()
        ),
        Article(
            id = &quot;article-id-2&quot;,
            title = &quot;article-title-2&quot;,
            content = &quot;article-content-2&quot;,
            authorId = &quot;user-id-2&quot;,
            createdAt = LocalDateTime.now().toString()
        ),
        Article(
            id = &quot;article-id-3&quot;,
            title = &quot;article-title-3&quot;,
            content = &quot;article-content-3&quot;,
            authorId = &quot;user-id-3&quot;,
            createdAt = LocalDateTime.now().toString()
        ),
    )
    private val users = mutableListOf(
        User(id = &quot;user-id-1&quot;, name = &quot;user-name-1&quot;),
        User(id = &quot;user-id-2&quot;, name = &quot;user-name-2&quot;),
        User(id = &quot;user-id-3&quot;, name = &quot;user-name-3&quot;),
    )
    private val comments = mutableListOf(
        Comment(id = &quot;comment-id-1&quot;, content = &quot;comment-content-1&quot;, articleId = &quot;article-id-1&quot;, userId = &quot;user-id-3&quot;),
        Comment(id = &quot;comment-id-2&quot;, content = &quot;comment-content-2&quot;, articleId = &quot;article-id-2&quot;, userId = &quot;user-id-3&quot;),
        Comment(id = &quot;comment-id-3&quot;, content = &quot;comment-content-3&quot;, articleId = &quot;article-id-2&quot;, userId = &quot;user-id-2&quot;),
        Comment(id = &quot;comment-id-4&quot;, content = &quot;comment-content-4&quot;, articleId = &quot;article-id-3&quot;, userId = &quot;user-id-3&quot;),
    )
    
    suspend fun findArticleById(id: String): Article? {
        delay(100)
        return articles.firstOrNull { it.id == id }
    }
    fun findAllArticles(): Flow&lt;Article&gt; = articles.asFlow()
    suspend fun findUserById(id: String): User? {
        delay(100)
        return users.firstOrNull { it.id == id }
    }
    fun findCommentsByArticleId(id: String): Flow&lt;Comment&gt; =
        comments.filter { it.articleId == id }.asFlow()
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@Component</span></span>
<span class="line"><span style="color: #F97583">object</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">ArticleService</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">private</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> articles </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">mutableListOf</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-title-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-content-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">        ),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-title-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-content-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">        ),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">            id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-title-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-content-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">        ),</span></span>
<span class="line"><span style="color: #E1E4E8">    )</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">private</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> users </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">mutableListOf</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-1&quot;</span><span style="color: #E1E4E8">, name </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-name-1&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">, name </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-name-2&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">, name </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-name-3&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">    )</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">private</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> comments </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">mutableListOf</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-id-1&quot;</span><span style="color: #E1E4E8">, content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-content-1&quot;</span><span style="color: #E1E4E8">, articleId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">, userId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-id-2&quot;</span><span style="color: #E1E4E8">, content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-content-2&quot;</span><span style="color: #E1E4E8">, articleId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-2&quot;</span><span style="color: #E1E4E8">, userId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-id-3&quot;</span><span style="color: #E1E4E8">, content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-content-3&quot;</span><span style="color: #E1E4E8">, articleId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-2&quot;</span><span style="color: #E1E4E8">, userId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">(id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-id-4&quot;</span><span style="color: #E1E4E8">, content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;comment-content-4&quot;</span><span style="color: #E1E4E8">, articleId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;article-id-3&quot;</span><span style="color: #E1E4E8">, userId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">),</span></span>
<span class="line"><span style="color: #E1E4E8">    )</span></span>
<span class="line"><span style="color: #E1E4E8">    </span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">findArticleById</span><span style="color: #E1E4E8">(id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">? {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">delay</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">100</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> articles.</span><span style="color: #B392F0">firstOrNull</span><span style="color: #E1E4E8"> { it.id </span><span style="color: #F97583">==</span><span style="color: #E1E4E8"> id }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">findAllArticles</span><span style="color: #E1E4E8">(): </span><span style="color: #B392F0">Flow</span><span style="color: #E1E4E8">&lt;</span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">&gt; </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> articles.</span><span style="color: #B392F0">asFlow</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">findUserById</span><span style="color: #E1E4E8">(id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8">? {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">delay</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">100</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> users.</span><span style="color: #B392F0">firstOrNull</span><span style="color: #E1E4E8"> { it.id </span><span style="color: #F97583">==</span><span style="color: #E1E4E8"> id }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">findCommentsByArticleId</span><span style="color: #E1E4E8">(id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Flow</span><span style="color: #E1E4E8">&lt;</span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">&gt; </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">        comments.</span><span style="color: #B392F0">filter</span><span style="color: #E1E4E8"> { it.articleId </span><span style="color: #F97583">==</span><span style="color: #E1E4E8"> id }.</span><span style="color: #B392F0">asFlow</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As we can see, we added two more &#8220;tables&#8221; along with simple functions to obtain data from them. </p>



<h3 class="wp-block-heading" id="h-update-controller">Update @Controller</h3>



<p>Then, let&#8217;s update our controller class:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@SchemaMapping
suspend fun author(article: Article): User =
    articleService.findUserById(article.authorId)!!
@SchemaMapping
suspend fun author(comment: Comment): User =
    articleService.findUserById(comment.userId)!!
@SchemaMapping
fun comments(article: Article): Flow&lt;Comment&gt; =
    articleService.findCommentsByArticleId(article.id)" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@SchemaMapping</span></span>
<span class="line"><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">author</span><span style="color: #E1E4E8">(article: </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">    articleService.</span><span style="color: #B392F0">findUserById</span><span style="color: #E1E4E8">(article.authorId)</span><span style="color: #F97583">!!</span></span>
<span class="line"><span style="color: #B392F0">@SchemaMapping</span></span>
<span class="line"><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">author</span><span style="color: #E1E4E8">(comment: </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">User</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">    articleService.</span><span style="color: #B392F0">findUserById</span><span style="color: #E1E4E8">(comment.userId)</span><span style="color: #F97583">!!</span></span>
<span class="line"><span style="color: #B392F0">@SchemaMapping</span></span>
<span class="line"><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">comments</span><span style="color: #E1E4E8">(article: </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Flow</span><span style="color: #E1E4E8">&lt;</span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">&gt; </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">    articleService.</span><span style="color: #B392F0">findCommentsByArticleId</span><span style="color: #E1E4E8">(article.id)</span></span></code></pre></div>



<p>As we can see, this time we leverage the <strong>@SchemaMapping</strong> annotation for our handlers. Pretty similar to what we did already.</p>



<p>The interesting part here is the <strong>parameters</strong>. Every handler takes the <strong>parent type as an argument</strong>. Meaning, that for the <code>article -&gt; author</code> parent-child relationship, we define the function that takes the article instance as an argument. And that&#8217;s it!</p>



<p>Of course, please the double exclamation (<code>!!</code>) should not land in the real, production-ready code😉</p>



<p>Anyway, when we rerun our test now, we will see the following: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;data&quot;: {
    &quot;articles&quot;: [
      {
        &quot;id&quot;: &quot;article-id-1&quot;,
        &quot;title&quot;: &quot;article-title-1&quot;,
        &quot;createdAt&quot;: &quot;2025-04-12T13:21:17.584507600&quot;,
        &quot;author&quot;: {
          &quot;id&quot;: &quot;user-id-2&quot;,
          &quot;name&quot;: &quot;user-name-2&quot;
        },
        &quot;comments&quot;: [
          {
            &quot;id&quot;: &quot;comment-id-1&quot;,
            &quot;content&quot;: &quot;comment-content-1&quot;,
            &quot;author&quot;: {
              &quot;name&quot;: &quot;user-name-3&quot;
            }
          }
        ]
      }
... more thingies " style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;articles&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">      {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-id-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;title&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;article-title-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;createdAt&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;2025-04-12T13:21:17.584507600&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;author&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">          </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-id-2&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">          </span><span style="color: #79B8FF">&quot;name&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-name-2&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">        },</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;comments&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">          {</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;comment-id-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #79B8FF">&quot;content&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;comment-content-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">            </span><span style="color: #79B8FF">&quot;author&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">              </span><span style="color: #79B8FF">&quot;name&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-name-3&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">            }</span></span>
<span class="line"><span style="color: #E1E4E8">          }</span></span>
<span class="line"><span style="color: #E1E4E8">        ]</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #FDAEB7; font-style: italic">...</span><span style="color: #E1E4E8"> </span><span style="color: #FDAEB7; font-style: italic">more</span><span style="color: #E1E4E8"> </span><span style="color: #FDAEB7; font-style: italic">thingies</span><span style="color: #E1E4E8"> </span></span></code></pre></div>



<p>And that&#8217;s what we expected. Awesome!</p>



<h2 class="wp-block-heading" id="h-graphql-mutations">GraphQL Mutations </h2>



<p>When we run the application right now, we see that we still miss two things that we defined- <strong>mutations</strong>.</p>



<p>So, before we add a new handler, let&#8217;s implement the following function in our service:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="suspend fun createArticle(input: CreateArticleInput): Article {
    delay(100)
    return Article(
        id = UUID.randomUUID().toString(),
        title = input.title,
        content = input.content,
        authorId = input.userId,
        createdAt = LocalDateTime.now().toString(),
    ).also { articles.add(it) }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">createArticle</span><span style="color: #E1E4E8">(input: </span><span style="color: #B392F0">CreateArticleInput</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #B392F0">delay</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">100</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">        id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> UUID.</span><span style="color: #B392F0">randomUUID</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">(),</span></span>
<span class="line"><span style="color: #E1E4E8">        title </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> input.title,</span></span>
<span class="line"><span style="color: #E1E4E8">        content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> input.content,</span></span>
<span class="line"><span style="color: #E1E4E8">        authorId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> input.userId,</span></span>
<span class="line"><span style="color: #E1E4E8">        createdAt </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> LocalDateTime.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">(),</span></span>
<span class="line"><span style="color: #E1E4E8">    ).</span><span style="color: #B392F0">also</span><span style="color: #E1E4E8"> { articles.</span><span style="color: #B392F0">add</span><span style="color: #E1E4E8">(it) }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As can be seen, we take the input, create a new <code>Article</code> instance, and insert that to the list.</p>



<p>With Kotlin <code>also</code> ,we can return at the same time the created instance and achieve a slightly cleaner code. To be even fancier, we could use a reference here: <code>.also(articles::add)</code> 😉 </p>



<p>Then, let&#8217;s add the appropriate handler to our controller:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@MutationMapping
suspend fun createArticle(@Argument input: CreateArticleInput): Article =
    articleService.createArticle(input)" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@MutationMapping</span></span>
<span class="line"><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">createArticle</span><span style="color: #E1E4E8">(</span><span style="color: #B392F0">@Argument</span><span style="color: #E1E4E8"> input: </span><span style="color: #B392F0">CreateArticleInput</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Article</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">    articleService.</span><span style="color: #B392F0">createArticle</span><span style="color: #E1E4E8">(input)</span></span></code></pre></div>



<p>As we can see, just like with @QueryMapping, this time, we mark the handler with <strong>@MutationMapping</strong> and our argument with <strong>@Argument</strong>. Nothing else is necessary to make our mutation work. </p>



<p>So, given that, let&#8217;s rerun the app and test our functionality:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="mutation someMutation {
  createArticle(
    input: {
      title: &quot;Awesome codersee Kotlin article&quot;, 
      content: &quot;Some content&quot;, 
      userId: &quot;user-id-3&quot;
    }
  ) {
    id
    title
    content
    author {
      id
      name
    }
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">mutation</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">someMutation</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #FFAB70">createArticle</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">input</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #9ECBFF">title</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;Awesome codersee Kotlin article&quot;</span><span style="color: #E1E4E8">, </span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #9ECBFF">content</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;Some content&quot;</span><span style="color: #E1E4E8">, </span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #9ECBFF">userId</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  ) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">title</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">content</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">author</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #FFAB70">name</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As a result, we should get the following:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;data&quot;: {
    &quot;createArticle&quot;: {
      &quot;id&quot;: &quot;0e51a902-835b-4e55-9b4a-f2dccd242ea7&quot;,
      &quot;title&quot;: &quot;Awesome codersee Kotlin article&quot;,
      &quot;content&quot;: &quot;Some content&quot;,
      &quot;author&quot;: {
        &quot;id&quot;: &quot;user-id-3&quot;,
        &quot;name&quot;: &quot;user-name-3&quot;
      }
    }
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;createArticle&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;0e51a902-835b-4e55-9b4a-f2dccd242ea7&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;title&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;Awesome codersee Kotlin article&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;content&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;Some content&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;author&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;id&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-id-3&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;name&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-name-3&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>Wonderful! We can see that with GraphQL mutations, we can not only create/modify things on our server. With this one query, we can also retrieve the data and the dependent objects😮</p>



<h2 class="wp-block-heading" id="h-error-handling-in-spring-graphql">Error Handling in Spring GraphQL</h2>



<p>As the last step, let&#8217;s add one more mutation to learn more about <strong>error handling</strong>.</p>



<p>First, let&#8217;s add the new custom exception ot our codebase in <code>Models.kt</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="data class GenericNotFound(val msg: String) : RuntimeException(msg)" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">data</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">GenericNotFound</span><span style="color: #E1E4E8">(</span><span style="color: #F97583">val</span><span style="color: #E1E4E8"> msg: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">) : </span><span style="color: #B392F0">RuntimeException</span><span style="color: #E1E4E8">(</span><span style="color: #B392F0">msg</span><span style="color: #E1E4E8">)</span></span></code></pre></div>



<p>Then, let&#8217;s implement the following function in <code>ArticleService</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="suspend fun addComment(id: String, input: AddCommentInput): Comment {
        delay(100)
        users.firstOrNull { it.id == input.userId }
            ?: throw GenericNotFound(&quot;User not found&quot;)
        return articles.firstOrNull { it.id == id }
            ?.let {
                Comment(
                    id = UUID.randomUUID().toString(),
                    articleId = id,
                    content = input.content,
                    userId = input.userId,
                ).also { comments.add(it) }
            }
            ?: throw GenericNotFound(&quot;Article not found&quot;)
    }" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">addComment</span><span style="color: #E1E4E8">(id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">, input: </span><span style="color: #B392F0">AddCommentInput</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #B392F0">delay</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">100</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">        users.</span><span style="color: #B392F0">firstOrNull</span><span style="color: #E1E4E8"> { it.id </span><span style="color: #F97583">==</span><span style="color: #E1E4E8"> input.userId }</span></span>
<span class="line"><span style="color: #E1E4E8">            ?: </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">GenericNotFound</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&quot;User not found&quot;</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> articles.</span><span style="color: #B392F0">firstOrNull</span><span style="color: #E1E4E8"> { it.id </span><span style="color: #F97583">==</span><span style="color: #E1E4E8"> id }</span></span>
<span class="line"><span style="color: #E1E4E8">            ?.</span><span style="color: #B392F0">let</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">                </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">                    id </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> UUID.</span><span style="color: #B392F0">randomUUID</span><span style="color: #E1E4E8">().</span><span style="color: #B392F0">toString</span><span style="color: #E1E4E8">(),</span></span>
<span class="line"><span style="color: #E1E4E8">                    articleId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> id,</span></span>
<span class="line"><span style="color: #E1E4E8">                    content </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> input.content,</span></span>
<span class="line"><span style="color: #E1E4E8">                    userId </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> input.userId,</span></span>
<span class="line"><span style="color: #E1E4E8">                ).</span><span style="color: #B392F0">also</span><span style="color: #E1E4E8"> { comments.</span><span style="color: #B392F0">add</span><span style="color: #E1E4E8">(it) }</span></span>
<span class="line"><span style="color: #E1E4E8">            }</span></span>
<span class="line"><span style="color: #E1E4E8">            ?: </span><span style="color: #F97583">throw</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">GenericNotFound</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&quot;Article not found&quot;</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span></code></pre></div>



<p>This time, we can see a more production-ready code.</p>



<p>If we want to add a comment to the article, we must first check if both the desired author and article exist, right?</p>



<p>If that is not the case, then we throw our custom exception.</p>



<p>Following, let&#8217;s add a new mutation handler: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@MutationMapping
suspend fun addComment(
    @Argument id: String,
    @Argument input: AddCommentInput,
): Comment =
    articleService.addComment(id, input)" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@MutationMapping</span></span>
<span class="line"><span style="color: #F97583">suspend</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">addComment</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #B392F0">@Argument</span><span style="color: #E1E4E8"> id: </span><span style="color: #B392F0">String</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #B392F0">@Argument</span><span style="color: #E1E4E8"> input: </span><span style="color: #B392F0">AddCommentInput</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">): </span><span style="color: #B392F0">Comment</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">    articleService.</span><span style="color: #B392F0">addComment</span><span style="color: #E1E4E8">(id, input)</span></span></code></pre></div>



<p>Now, when we rerun the app and execute the following test: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="mutation anotherMutation {
  addComment(
    articleId: &quot;non-existing&quot;
    input: {userId: &quot;user-id-1&quot;, content: &quot;My comment&quot;}
  ) {
    id
    content
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #F97583">mutation</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">anotherMutation</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #FFAB70">addComment</span><span style="color: #E1E4E8">(</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">articleId</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;non-existing&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">input</span><span style="color: #E1E4E8">: {</span><span style="color: #9ECBFF">userId</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;user-id-1&quot;</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">content</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;My comment&quot;</span><span style="color: #E1E4E8">}</span></span>
<span class="line"><span style="color: #E1E4E8">  ) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">id</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #FFAB70">content</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>We will see the following error: </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;errors&quot;: [
    {
      &quot;message&quot;: &quot;INTERNAL_ERROR for f62a4c7e-1&quot;,
      &quot;locations&quot;: [
        {
          &quot;line&quot;: 52,
          &quot;column&quot;: 3
        }
      ],
      &quot;path&quot;: [
        &quot;addComment&quot;
      ],
      &quot;extensions&quot;: {
        &quot;classification&quot;: &quot;INTERNAL_ERROR&quot;
      }
    }
  ],
  &quot;data&quot;: {
    &quot;addComment&quot;: null
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;errors&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">    {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;message&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;INTERNAL_ERROR for f62a4c7e-1&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;locations&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">        {</span></span>
<span class="line"><span style="color: #E1E4E8">          </span><span style="color: #79B8FF">&quot;line&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">52</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">          </span><span style="color: #79B8FF">&quot;column&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">3</span></span>
<span class="line"><span style="color: #E1E4E8">        }</span></span>
<span class="line"><span style="color: #E1E4E8">      ],</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;path&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #9ECBFF">&quot;addComment&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      ],</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;extensions&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;classification&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;INTERNAL_ERROR&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  ],</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;addComment&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">null</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>And this is not what we wanted, right? </p>



<h3 class="wp-block-heading" id="h-graphqlexceptionhandler-and-controlleradvice">GraphQlExceptionHandler and ControllerAdvice</h3>



<p>One of the solutions we can have in such a situation is a combination of ControllerAdvice and GraphQlExceptionHandler.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>If you would like to learn more about ControllerAdvice and RestControllerAdvice, then check out my <a href="https://blog.codersee.com/controlleradvice-vs-restcontrolleradvice/">other article</a>.</p>
</blockquote>



<p>So, as the next step, let&#8217;s add the <code>GlobalExceptionHandler</code> class to the project:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="@ControllerAdvice
class GlobalExceptionHandler {
    @GraphQlExceptionHandler
    fun handleGenericNotFound(ex: GenericNotFound): GraphQLError =
        GraphQLError.newError()
            .errorType(ErrorType.DataFetchingException)
            .message(ex.msg)
            .build()
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #B392F0">@ControllerAdvice</span></span>
<span class="line"><span style="color: #F97583">class</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">GlobalExceptionHandler</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #B392F0">@GraphQlExceptionHandler</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">fun</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">handleGenericNotFound</span><span style="color: #E1E4E8">(ex: </span><span style="color: #B392F0">GenericNotFound</span><span style="color: #E1E4E8">): </span><span style="color: #B392F0">GraphQLError</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span></span>
<span class="line"><span style="color: #E1E4E8">        GraphQLError.</span><span style="color: #B392F0">newError</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">            .</span><span style="color: #B392F0">errorType</span><span style="color: #E1E4E8">(ErrorType.DataFetchingException)</span></span>
<span class="line"><span style="color: #E1E4E8">            .</span><span style="color: #B392F0">message</span><span style="color: #E1E4E8">(ex.msg)</span></span>
<span class="line"><span style="color: #E1E4E8">            .</span><span style="color: #B392F0">build</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<p>As we can see, inside it, we implement a function that takes the <strong>GenericNotFound</strong> as an argument. This way, whenever our custom exception is thrown, Spring will return the <strong>GraphQLError</strong> instance with our config instead.</p>



<p>As a result, when we retest the application, we should get the following JSON:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#24292e"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="{
  &quot;errors&quot;: [
    {
      &quot;message&quot;: &quot;Article not found&quot;,
      &quot;locations&quot;: [],
      &quot;extensions&quot;: {
        &quot;classification&quot;: &quot;DataFetchingException&quot;
      }
    }
  ],
  &quot;data&quot;: {
    &quot;addComment&quot;: null
  }
}" style="color:#e1e4e8;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-dark" style="background-color: #24292e" tabindex="0"><code><span class="line"><span style="color: #E1E4E8">{</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;errors&quot;</span><span style="color: #E1E4E8">: [</span></span>
<span class="line"><span style="color: #E1E4E8">    {</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;message&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;Article not found&quot;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;locations&quot;</span><span style="color: #E1E4E8">: [],</span></span>
<span class="line"><span style="color: #E1E4E8">      </span><span style="color: #79B8FF">&quot;extensions&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">        </span><span style="color: #79B8FF">&quot;classification&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #9ECBFF">&quot;DataFetchingException&quot;</span></span>
<span class="line"><span style="color: #E1E4E8">      }</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">  ],</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">&quot;data&quot;</span><span style="color: #E1E4E8">: {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #79B8FF">&quot;addComment&quot;</span><span style="color: #E1E4E8">: </span><span style="color: #79B8FF">null</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div>



<h2 class="wp-block-heading" id="h-spring-graphql-with-kotlin-coroutines-summary">Spring GraphQL with Kotlin Coroutines Summary</h2>



<p>And that&#8217;s all for this article on how to work with Kotlin coroutines and Flows in the Spring Boot GraphQL project.</p>



<p>As always, you can find the source code in my <a href="https://github.com/codersee-blog/spring-boot-3-graphql-kotlin-coroutines" target="_blank" rel="noreferrer noopener">GitHub repostory</a>.</p>
<p>The post <a href="https://blog.codersee.com/spring-graphql-kotlin-coroutines/">Spring for GraphQL with Kotlin Coroutines</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/spring-graphql-kotlin-coroutines/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: blog.codersee.com @ 2026-02-27 03:25:27 by W3 Total Cache
-->