You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -3,7 +3,7 @@ title = "Getting started with GraphQL Java and Spring Boot"
3
3
author = "Andreas Marek"
4
4
tags = []
5
5
categories = []
6
-
date = 2018-10-22T01:00:00+10:00
6
+
date = 2019-01-23
7
7
toc = "true"
8
8
+++
9
9
@@ -18,9 +18,9 @@ For example we wanna query the details for specific book from a online store bac
18
18
19
19
With GraphQL you send the following query to server to get the details for the book with the id "123":
20
20
21
-
{{< highlight graphql "linenos=table" >}}
21
+
{{< highlight scala "linenos=table" >}}
22
22
{
23
-
book(id: "123"){
23
+
bookById(id: "123"){
24
24
id
25
25
name
26
26
pageCount
@@ -32,17 +32,20 @@ With GraphQL you send the following query to server to get the details for the b
32
32
}
33
33
{{< / highlight >}}
34
34
35
-
This is not JSON (even if it looks remotely similar), but it is a GraphQL query.
35
+
This is not JSON (even if it looks remotely similar), it is a GraphQL query.
36
36
37
37
But the response is normal JSON:
38
38
{{< highlight json "linenos=table" >}}
39
-
{
40
-
"id":"123",
41
-
"name":"Harry Potter and the Philosopher's Stone",
42
-
"pageCount":223,
43
-
"author": {
44
-
"firstName":"J. K.",
45
-
"lastName":"Rowling"
39
+
{
40
+
"bookById":
41
+
{
42
+
"id":"123",
43
+
"name":"Harry Potter and the Philosopher's Stone",
44
+
"pageCount":223,
45
+
"author": {
46
+
"firstName":"J. K.",
47
+
"lastName":"Rowling"
48
+
}
46
49
}
47
50
}
48
51
{{< / highlight >}}
@@ -51,62 +54,45 @@ One very important property of GraphQL is that it is statically typed: the serve
51
54
52
55
The schema for the above query looks like this:
53
56
54
-
{{< highlight graphql "linenos=table" >}}
57
+
{{< highlight scala "linenos=table" >}}
55
58
type Query {
56
-
book(id: ID): Book
59
+
bookById(id: ID): Book
57
60
}
58
61
59
62
type Book {
60
63
id: ID
61
64
name: String
62
65
pageCount: Int
63
-
author: Person
66
+
author: Author
64
67
}
65
68
66
-
type Person {
69
+
type Author {
70
+
id: ID
67
71
firstName: String
68
72
lastName: String
69
73
}
70
74
{{< / highlight >}}
71
75
72
-
This tutorial will focus on how to implement a GraphQL server in Java.
76
+
This tutorial will focus on how to implement a GraphQL server with schema in Java.
73
77
74
78
We barely touched GraphQL. Further information can be found on the official page: https://graphql.github.io/learn/
75
79
76
-
77
80
# GraphQL Java Overview
78
81
79
82
[GraphQL Java](https://www.graphql-java.com) is the Java (server) implementation for GraphQL.
80
83
The are several repositories in the GraphQL Java Github org. The most important one is the [GraphQL Java Engine](https://github.com/graphql-java/graphql-java) which is basis for everything else.
81
84
82
-
We will also use the [GraphQL Java Spring Boot](https://github.com/graphql-java/graphql-java-spring) adapter, which takes care of exposing your GraphQL API via HTTP.
83
-
84
-
GraphQL Java itself is only concerned with executing queries. It doesn't deal with any HTTP or JSON related topics. For these aspects we will use [Spring Boot](https://spring.io/projects/spring-boot).
85
+
GraphQL Java Engine itself is only concerned with executing queries. It doesn't deal with any HTTP or JSON related topics. For these aspects we will use the [GraphQL Java Spring Boot](https://github.com/graphql-java/graphql-java-spring) adapter which takes care of exposing our API via Spring Boot over HTTP.
85
86
86
87
The main steps of creating a GraphQL Java server are:
87
88
88
89
1. Defining a GraphQL Schema.
89
90
2. Defining on how the actual data for a query is fetched.
90
91
91
-
92
92
# Our example API: getting book details
93
93
94
-
Our example app we will build is a simple online store for books.
95
-
We assume the very simple user flow:
96
-
97
-
the user comes to our page and sees all available books for order.
98
-
They can select a specific book and look up the details. If they like it they can order it.
99
-
100
-
We will build a GraphQL server which will cover the following use cases:
101
-
102
-
1. get a list of available books
103
-
1. get specific book details
104
-
105
-
We will incrementally build our app.
106
-
107
-
> **What about the schema/API design?**<br/>
108
-
Schema and API design itself is interesting and challenging but we will focus on implementing the server and not discuss the actual schema design choices.
109
-
94
+
Our example app will be a simple API to get details for a specific book.
95
+
This is in no way a comprehensive API, but it is enough for this tutorial.
110
96
111
97
# Create a Spring Boot app
112
98
@@ -121,7 +107,7 @@ Select:
121
107
For the project metadata we use:
122
108
123
109
- Group: `com.graphql-java.tutorial`
124
-
- Artifact: `online-store`
110
+
- Artifact: `book-details`
125
111
126
112
As dependency we just select `Web`.
127
113
@@ -132,90 +118,142 @@ We are adding three dependencies to our project inside the `dependencies` sectio
132
118
133
119
the first two are GraphQL Java and GraphQL Java Spring and then we also add [Google Guava](https://github.com/google/guava). Guava is not strictly needed but it will make our life a little bit easier.
We are creating a new file `schema.graphqls` in `src/main/resources` with the following content:
147
136
148
-
{{< highlight graphql "linenos=table" >}}
137
+
{{< highlight scala "linenos=table" >}}
149
138
type Query {
150
-
books: [Books]
151
-
bookById(id: ID!): Book
139
+
bookById(id: ID): Book
152
140
}
153
141
154
142
type Book {
155
143
id: ID
156
144
name: String
145
+
pageCount: Int
146
+
author: Author
157
147
}
158
148
149
+
type Author {
150
+
id: ID
151
+
firstName: String
152
+
lastName: String
153
+
}
159
154
{{< / highlight >}}
155
+
<p/>
160
156
161
-
This schema defines two top level fields (fields in the type `Query`): `books` which results in a list of `Book`s and a `bookById` to query a specific Book by id.
157
+
This schema defines one top level field (field in the type `Query`): `bookById` which returns the details of a specific book.
162
158
163
-
It also defines the type `Book` which has two fields: `id` and `name`.
159
+
It also defines the type `Book` which has the fields: `id`, `name`, `pageCount` and `author`.
160
+
`author` is of type `Author`, which is defined after `Book`.
164
161
165
162
> The Domain Specific Language shown above which is used to describe a schema is called Schema Definition Language or SDL.
166
163
167
164
But so far it is just a normal text. We need to "bring it to live" by reading the file and parsing it.
168
-
We are using Guava to read the file at runtime from our classpath:
165
+
166
+
We are creating a new `GraphQLProvider` class in the package `com.graphqljava.tutorial.bookdetails` with an `init` method which will create a `GraphQL` instance:
We are using Guava to read the file at runtime from our classpath, then create a `GraphQLSchema` and `GraphQL` instance. This `GraphQL` instance is exposed as Spring Bean. The GraphQL Java Spring adapter will use that `GraphQL` instance to expose it the schema over HTTP on the default url `/graphql`.
174
197
175
-
We now using GraphQL Java for the first time: We are transforming the `sdl` into a `TypeDefinitionRegistry`:
176
198
199
+
What we still need to do is to implement the `buildSchema` method which creates the `GraphQLSchema` instance:
177
200
178
201
{{< highlight java "linenos=table" >}}
179
-
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
202
+
@Autowired
203
+
GraphQLDataFetchers graphQLDataFetchers;
204
+
205
+
private GraphQLSchema buildSchema(String sdl) {
206
+
TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
207
+
RuntimeWiring runtimeWiring = buildWiring();
208
+
SchemaGenerator schemaGenerator = new SchemaGenerator();
This `TypeDefinitionRegistry` is just a parsed version of the schema definition file.
224
+
`TypeDefinitionRegistry` is the parsed version of our schema file. `SchemaGenerator` combines the `TypeDefinitionRegistry` with `RuntimeWiring` to actually make the `GraphQLSchema`.
183
225
184
-
## Creating a GraphQLSchema
226
+
`buildRuntimeWiring` uses the `graphQLDataFetchers` bean to actually register two `DataFetcher`:
185
227
186
-
The `typeRegistry` defined above is just types: it describes how the schema looks like, but not how it actually works when a query is executed.
228
+
- One to retrieve a book with a specific ID
229
+
- One to get the author for a specific book.
187
230
231
+
`DataFetcher` and how to implement the `GraphQLDataFetcher` bean is explained in the next section.
188
232
189
233
# DataFetchers
190
234
191
235
Probably the most important concept for a GraphQL Java server is a `DataFetcher`:
192
236
A `DataFetcher` fetches the Data for one field while the query is executed.
193
237
194
238
While GraphQL Java is executing a query it calls the appropriate `DataFetcher` for each field it encounters in query.
195
-
A `DataFetcher` is a Interface with a single method, taking a single argument of type `DataFetcherEnvironment`.
239
+
A `DataFetcher` is an Interface with a single method, taking a single argument of type `DataFetcherEnvironment`:
196
240
197
-
For our first iteration we are doing the simplest possible thing that works: we are fetching the books we wanna display from in-memory.
198
-
199
-
Our code looks like this:
200
241
201
242
{{< highlight java "linenos=table" >}}
202
-
243
+
public interface DataFetcher<T> {
244
+
T get(DataFetchingEnvironment dataFetchingEnvironment) throws Exception;
245
+
}
203
246
{{< / highlight >}}
247
+
<p/>
204
248
249
+
Important: **Every** field from the schema has a `DataFetcher` associated with. If you don't specify any `DataFetcher` for a specific field the default `PropertyDataFetcher` is used.
205
250
206
-
Important: **Every** field from the schema has a `DataFetcher` associated with. Most of them have the a default `DataFetcher` of type `PropertyDataFetcher`.
207
-
208
-
# Exposing the schema via HTTP
209
-
210
-
The last step is to actually expose the GraphQL schema via HTTP. This is done via the GraphQL Java Spring adapter.
251
+
We are creating a new class `GraphQLDataFetchers
211
252
212
-
The only thing you have todo is to actually define a `Bean` of type `GraphQL` in you Spring Boot app.
0 commit comments