Home
New @GraphQLIgnore Annotation: Code-First Schema in Spring
I recently incorporated the spring-graphql
library into a project that had been using the graphql-java-annotations
library for satisfying the “code-first” approach to GraphQL schema generation.
The problem I faced: how to unify the interfaces defining the schema, with the controllers defining the actual data fatchers executed at runtime?
As an example, a method used to generate the schema using graphql-java-annotations
might be:
public interface Foo {
@GraphQLField
@GraphQLNonNull Bar bar(@GraphQLName("baz") @GraphQLNonNull String baz);
}
while the method mapped to that field at runtime using spring-graphql
might be:
public class FooController {
@SchemaMapping
public Bar bar(
Foo foo,
GraphQLContext context,
@Argument String baz) {
// ...
}
}
The schema I was working with was non-trivial, so I ruled out keeping these definitions separate, as it would have quickly become chaotic.
So I experimented with various approaches to making the controllers implement the original interfaces, but ultimately abandoned that approach after realizing it wasn’t possible.
Eventually I merged the interface definitions into the controllers, producing methods like this:
public class FooController {
@SchemaMapping
@GraphQLField
public @GraphQLNonNull Bar bar(
Foo foo,
GraphQLContext context,
@Argument @GraphQLName("baz") @GraphQLNonNull String baz) {
// ...
}
}
New problem: what to do about parameters foo
and context
?
foo
is the “source” object on which this controller is operatingcontext
is the extra state we have for this particular GraphQL request
If we run graphql-java
over this method definition and ask it to produce a schema:
foo
is a valid schema type, but by including it, any caller of this field will be contractually required to provide aFoo
; this is undesirable, as aFoo
need only be supplied at runtime by the environmentcontext
is not a valid schema type, sographql-java
will abort with an error
Prior to December 2023, there was no way to simply ignore these parameters at schema-generation time. In PR #299 of the graphql-java-annotations
library, I added a new annotation @GraphQLIgnore
that does just that: ignores any parameter on which it is present. Now we can write:
public class FooController {
@SchemaMapping
@GraphQLField
public @GraphQLNonNull Bar bar(
@GraphQLIgnore Foo foo,
@GraphQLIgnore GraphQLContext context,
@Argument @GraphQLName("baz") @GraphQLNonNull String baz) {
// ...
}
}
The end result is that this single method definition can be used both at compile-time for schema generation and at runtime for execution, without any duplication or extra maintenance burden. This should make the code-first GraphQL development style much more pleasant when using Spring’s GraphQL runtime library.