spring-graphql
spring-graphql copied to clipboard
Do not ignore a DataFetcher with a DataFetcherFactories wrapper
schem.graphqls
directive @UpperCase on FIELD_DEFINITION
type Query{
hello: String @UpperCase
}
QueryMapping
@QueryMapping
public Mono<String> hello(){
return Mono.just("hello");
}
SchemaDirectiveWriting
@Override
public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> environment) {
DataFetcher<?> dataFetcher = DataFetcherFactories.wrapDataFetcher(environment.getFieldDataFetcher(), ((dataFetchingEnvironment, value) -> {
return Mono.just("HELLO");
}));
return environment.setFieldDataFetcher(dataFetcher);
}
I was expecting "HELLO" and but it returns this,
{
"data": {
"hello": "MonoJust"
}
}
DataFetherFactories supports a function to apply to the value of a CompletionStage. Spring for GraphQL applies similar decoration to support Reactor types. However, it ignores any DataFetchers under the graphql package, and that includes DataFetcherFactories.
I can add an exclusion for DataFetcherFactories but in general, if you want to support a directive for Reactor return types you will need to the wrapping yourself anyway. Something like this:
@Override
public GraphQLFieldDefinition onField(SchemaDirectiveWiringEnvironment<GraphQLFieldDefinition> environment) {
if (environment.getDirective("UpperCase") == null) {
return environment.getElement();
}
DataFetcher<?> fieldDataFetcher = environment.getFieldDataFetcher();
return environment.setFieldDataFetcher(dataFetchingEnvironment -> {
Object value = fieldDataFetcher.get(dataFetchingEnvironment);
if (value instanceof Mono) {
return ((Mono<?>) value).map(s -> (s instanceof String ? ((String) s).toUpperCase() : s));
}
else if (value instanceof String) {
return ((String) value).toUpperCase();
}
else {
return value;
}
});
}