GraphQL with spring-boot-starter-graphql
Finally, after 10 months of waiting GraphQL is integrated with the latest release of spring boot 2.7.0. With this release, spring-boot-starter-graphql replaces the current GraphQL java spring. For more details on this release check here.
In this article, we’ll see how you can start using this new graphql starter or simply migrate your existing project. Here, I am using my previous project that was built with graphql java spring.
Requirements
Setup you’ll need:
- Basic understanding of spring boot and GraphQL
- Existing graphql java project or clone one here
- Docker installed on your machine
- Intellij or IDE of your choice
- Postman for testing the API
Project Migration
Unlike before, with spring boot 2.7.0 we only need one dependency to integrate GraphQL in our project. So I started by upgrading the spring boot version to
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/>
Then I removed the previous graphql dependencies graphql-java-tools and graphql-spring-boot-starter.
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>12.0.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>12.0.0</version>
</dependency>
And added the new spring boot graphql starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
After this, remove all the implemented Resolvers and clean the project by removing all the imports from graphql java spring.
Now our project is clean and updated with the new dependencies. According to the spring graphql documentation, the biggest changes come with the new annotated controllers. The default location for schema files are src/main/resources/graphql/**. This is the case here, so we don’t need to touch the graphql schema files. All files will be picked up automatically by spring graphql starter.
You can also customize the schema file location in the application.properties. But here we’ll go with the defaults.
GraphQL Annotations
With Graphql spring java the resolvers component is needed to implement GraphQLQueryResolver or GraphQLMutationResolver classes. But with the spring boot starter graphql, it’s moved to an annotation-based programming model. In short previous resolvers are replaced by annotations:
GraphQLMutationResolver -> @MutationMappingGraphQLQueryResolver -> @QueryMapping
And the @Controller component uses the annotated handler methods to bind and resolve graphql schema fields/queries.
Query Mapping
As the name suggests this annotation maps the handler method to the query type in graphql schema.
Now let’s configure our query methods by annotating them with @QueryMapping. For mapping query argument we can use the annotation @Argument. For more flexibility you can also define alias names for the arguments for example
The query getBookByName has an argument filter in the schema and in the handler method, it’s bookFilter. So we need to define an alias with the @Argument(“filter”). If you forget to do this, your project will just deploy successfully but the query will end up with NPE. Which I wasted some time on, and later figured out it was just missing the right matching argument names.
Schema Mapping
This annotation maps and binds a handler with the field in the GraphQL schema, it can be used at the method or class level. It accepts two parameters typeName= and field=. It’s also the parent annotations of the other query-specific annotations.
We’ll need this annotation to resolve the author field type of the Book type.
Here we define the @SchemaMapping annotation with parameters
- typeName= Book, which is the type to which the author field belongs
- field= author, to specify which field of the specified typeName will be resolved by this handler method.
After, I defined the argument on the field, order with the @Argument annotation. As it has the same name order both in schema and handler method spring will map it automatically. Since we are defining the schema annotation at the method level the previous BookAuthorResolver class is unnecessary so I removed it and moved the method to the BookQuery class.
Mutation Mapping
This annotation maps handler methods with the mutation query in the GraphQL schema.
Just like we changed for the queryMapping, add the @MutationMapping to the mutation query method and annotate the mutation argument with @Argument(“input”) annotation with the alias.
Since Mutation and Query mapping annotations are meta-annotations of SchemaMapping, we can also replace them like this.
TEST API
Now all the changes are done let's build and run the project.
mvn clean install
Then deploy with docker.
docker-compose up -d
Let’s test one query first
As mentioned in the specs, the new spring graphql starter uses Runtime wiring to register handler methods to the graphql.schema.Datafetcher. Therefore even if you annotate a handler method wrong like, instead of @QueryMapping you accidentally put @MutationMapping
You won’t see any errors but the result won’t be the one expected. So just be careful while annotating the handler methods.
Now let’s test one mutation.
The API works as expected. I hope this quick article will help you get started with the new spring-boot-graphql-starter and play with the other cool features it has. You can check out this project on github here. If you like this article be sure to check out my other articles related to spring boot.