IntroductionGraphQL Spring Boot is a powerful library that allows developers to quickly and easily set up a Java implementation of a GraphQL server in a matter of minutes by leveraging the widely popular Spring Framework. However—like many libraries written in a convention over configuration paradigm—this ease of use comes under the assumption that the developer follows a particular pattern when coding against the framework. This blog will explain how to increase your leg room as a developer when wiring your GraphQL types to your Java backend.
Before going into detail of how the mapping process works using GraphQL Spring Boot, note that the traditional list of GraphQL scalar types is expanded by the library to include some common Java variable types: Long, Short, Byte, BigDecimal, and BigInteger.
For every GraphQL type, there is a corresponding Java class modeling that type (similar to Jackson). Your resolvers will be a method named exactly like the field or the fields getter. For example, given the following GraphQL type:
the expectation is that in your project there is a Java counterpart:
Easy, right? That’s because it is. This is also the extent of the knowledge necessary regarding how types map to classes to get a production ready GraphQL server up and running. The library will iterate through every GraphQLs file under resources/schema. For each type—enum and input—it encounters, it will look for a Java class reflecting the exact same name to create a map (literally a map structure) from your GraphQL types to your Java classes.
Drifting from this naming practice
What if in your GraphQL schema definition there are types that will not have an equivalently named Java class? This scenario may occur when your type names have to follow a particular pattern that your Java classes do not or when your types with specific names have to map to classes from an imported library where you do not control class naming.
Let’s imagine that all your GraphQL types must be prefixed with “Mf” (for mobileforming). This would obviously be a bad pattern to carry over to your Java class naming standards. Thus, you will end up with a naming discrepancy between your GraphQL types and your Java classes—leading to issues when GraphQL Spring Boot attempts to wire up your schema with the appropriate classes.
All of these type to class mappings are maintained in a bean of the class SchemaParserDictionary—which is a wrapper over an actual map structure where the keys are Strings representing GraphQL type names and the values are Class<?> objects representing the Java class. By getting a handle on this bean or preferably auto wiring your own, you gain the ability to control which class a type will get mapped to—regardless of naming. Attaching your own SchemaParserDictionary bean to the Spring application context would be the simplest solution. Class-based bean instantiation is perfectly suited for such a task:
In the code above, we are mapping our renamed GraphQL type “MfPhone” to our Phone class. The auto-configuration performed by GraphQL Spring Boot will continue its regular process of type name -> class name for any other types defined in our schema—keeping our “MfPhone” type mapped to our Phone class. We can add as many definitions to our SchemaParserDictionary and even pass an existing Map<String, Class<?>> object to its #add method—therein, adding all our key value pairs to the dictionary.
Real World Example
If the case is that GraphQL types will conform to different naming standards than Java classes, it’s cleaner to perform this process of adding entries to your SchemaParserDictionary in bulk. The following example is a proven method of applying this practice. Consider a scenario where GraphQL types have to obey a naming standard where they must contain a prefix. The classes these types have to map to are shared among multiple consumer facing projects, and therefore, renaming these classes to satisfy such a particular requirement is not a viable option. Because all of the classes being mapped simply need a prefix, you only need to create a class that wraps over a set of Class<?> and include a method returning a map—the values are the Class objects in the set and the keys are the Class names with that prefix. This is how it looks with our “Mf” example from before:
By creating a component out of the class, you will easily be able to inject it into a @Bean method:
The end result is that we have a predefined set of classes that will be added to our SchemaParserDictionary bean with the amendment that our corresponding GraphQL types are prefixed by “Mf.” That’s all there is to it!
A handle on the SchemaParserDictionary bean provides developers a great method for directing mappings between types and classes when the default methodology won’t suffice. With it, developers have complete control over which class they want a type to wire up against.