I try to add a custom scalar type for GraphQL Java. I need it to resolve a Map without creating a type for it because it is a common return type in my logic.
I followed the instruction (here: http://graphql-java.readthedocs.io/en/latest/scalars.html) to create a scalar type.
This is my MapScalar.java
public class MapScalar {
private static final Logger LOG = LoggerFactory.getLogger(MapScalar.class);
public static final GraphQLScalarType MAP = new GraphQLScalarType("Map", "A custom map scalar type", new Coercing() {
@Override
public Object serialize(Object dataFetcherResult) throws CoercingSerializeException {
Map map = null;
try {
map = Map.class.cast(dataFetcherResult);
} catch (ClassCastException exception) {
throw new CoercingSerializeException("Could not convert " + dataFetcherResult + " into a Map", exception);
}
return map;
}
@Override
public Object parseValue(Object input) throws CoercingParseValueException {
LOG.warn("parseValue called");
return null;
}
@Override
public Object parseLiteral(Object input) throws CoercingParseLiteralException {
LOG.warn("parseLiteral called");
return null;
}
});
}
I added this scalar instance to RunTimeWiring
final RuntimeWiring runtimeWiring = newRuntimeWiring()
.type(queryTypeFactory.getQueryBaseQueryType()) // just convenience methods I made
.type(queryTypeFactory.getPageQueryType(viewName)) // ...
.type(queryTypeFactory.getContentQueryType(viewName)) // ...
.type(queryTypeFactory.getPictureQueryType()) // ...
.type(queryTypeFactory.getSettingQueryType()) // just convenience methods I made
.scalar(MapScalar.MAP) // added new scalar here
.build();
I defined this MapDataFetcher
@Component
public class MapDataFetcher implements DataFetcher {
@Override
public Object get(DataFetchingEnvironment environment) {
String fieldName = environment.getField().getName();
Content source = Content.class.cast(environment.getSource());
return source.getStruct(fieldName).toNestedMaps(); // returns a Map<String,Object>
}
}
And the schema for this field/scalar is defined as followed:
type Content {
//... other fields
settings: Map
}
When debugging the RunTimeWiring
everthing seems fine. The scalar has been added to the default scalars:
Still this error occurs:
SCHWERWIEGEND: Servlet.service() for servlet [cae] in context with path [/blueprint] threw exception [Request processing failed; nested exception is SchemaProblem{errors=[The field type 'Map' is not present when resolving type 'Content' [@10:1], The field type 'Map' is not present when resolving type 'Setting' [@28:1]]}] with root cause
SchemaProblem{errors=[The field type 'Map' is not present when resolving type 'Content' [@10:1], The field type 'Map' is not present when resolving type 'Setting' [@28:1]]}
I can not find any hind in the tutorials to find out what I am missing out to make it work. I understand that there is a missing type here. But creating a new Type with newRunTimeWiring().type()
is a for creating Non-Scalar types isn't it? Or do I still need to create a Map
type in there?
There was just one little thing missing nobody mentioned in the tutorials.
I had to add this so Map
is actually recognized as a scala type
add to schema definition file:
scalar Map
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With