Adding Custom Directives
GraphQL directives provide a way to decorate parts of a GraphQL schema with additional metadata or behavior. Custom directives enable the powerful extension of GraphQL's base functionalities through your own reusable logic.
Use Cases¶
Custom directives may be useful for a variety of tasks, including but not limited to:
- Validation
- Authorization
- Data Transformation or Augmentation
- Caching or Optimizations
- Monitoring or Logging
- Adding Field Metadata
Implementing a Custom Directive¶
Consider a scenario where you want to modify the formatting of a returned String
field so that the value is transformed to uppercase. You have a couple options: either you can write a utility class within your application code and manually invoke it wherever necessary, or you can create a custom @uppercase
GraphQL directive and apply the transformation in a declarative way across your schema where needed:
directive @uppercase on FIELD_DEFINITION
type Query {
greeting: String @uppercase
}
Here is the backing code needed to support this @uppercase
directive:
package com.example.demo.directives;
import com.netflix.graphql.dgs.DgsDirective;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetcherFactories;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLFieldsContainer;
import graphql.schema.idl.SchemaDirectiveWiring;
import graphql.schema.idl.SchemaDirectiveWiringEnvironment;
@DgsDirective(name = "uppercase")
public class UppercaseDirective implements SchemaDirectiveWiring {
@Override
public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> env) {
GraphQLFieldsContainer fieldsContainer = env.getFieldsContainer();
GraphQLFieldDefinition fieldDefinition = env.getFieldDefinition();
DataFetcher<?> originalDataFetcher = env.getCodeRegistry().getDataFetcher(fieldsContainer, fieldDefinition);
DataFetcher<?> dataFetcher = DataFetcherFactories.wrapDataFetcher(
originalDataFetcher,
(dataFetchingEnvironment, value) -> {
if (value instanceof String) {
return ((String) value).toUpperCase();
}
return value;
}
);
env.getCodeRegistry().dataFetcher(fieldsContainer, fieldDefinition, dataFetcher);
return fieldDefinition;
}
}
In this example, the UppercaseDirective
class implements SchemaDirectiveWiring
and overrides its onField
method, where the logic for transforming the value to uppercase lives. The original DataFetcher
for the field is wrapped in a new one, which applies the uppercase logic before returning the value. The @DgsDirective
annotation ensures that the custom directive is registered with the Spring framework.
Custom directives can be implemented for various components of your GraphQL schema, not just field definitions. To learn more, explore the graphql-java SDL directives documentation.