Custom Scalar in Graphql-java
Asked Answered
T

3

11

We are planning use Graphql as backend server in our application. We choose Graphql-Java to develop our POC. We came across a stituation to create our own scalartype to handle java.util.Map object type.

we havent found any documentation regarding creating a custom scalar type. In example code as below

RuntimeWiring buildRuntimeWiring() {
    return RuntimeWiring.newRuntimeWiring()
            .scalar(CustomScalar)

how to was the implementation done for CustomScalar object. need help.

Taligrade answered 4/9, 2017 at 10:10 Comment(0)
R
8

To get a general idea how to make a scalar, just take a look into the existing ones and do something similar.

graphql-java also has a separate project for extra scalars: graphql-java-extended-scalars. And there you can find the object scalar (a.k.a. JSON scalar), that can be used for dynamic structures, like Maps.

Register it via:

RuntimeWiring.newRuntimeWiring().scalar(ExtendedScalars.Object)
Ramakrishna answered 6/9, 2017 at 11:33 Comment(9)
how do I utilize above scaler into my code? I've a Spring-boot application and it'll help if you could provide an example.Descry
@Descry How do you use any built-in scalar, like String or Integer? There's no difference.Ramakrishna
Not sure I understand what you mean. But those; String and Integer are built in and it all happens automatically. So above scalar is for object and I would need to create one for Map, right? Do you've an example. Also what is the significant of the name argument? Is that the name of the type we defined in the schema?Descry
@Descry Happens automatically? Does that mean you're using GraphQL-SPQR? If so, annotate the type at the place of use with @GraphQLScalar (e.g. annotated a method argument) or use a different ScalarMappingStrategy (e.g. gen.withScalarMappingStrategy(new MapScalarStrategy())). Without SPQR, there's no automatic mapping. You set a type of each field, e.g. newFieldDefinition().type(Scalars.GraphQLString), so you can use newFieldDefinition().type(Scalars.graphQLObjectScalar("typeName")) instead. You'll get a Map just like for any object input, but with a dynamic structure.Ramakrishna
@Descry If using schema-first with graphql-java directly, you can use a custom scalar via RuntimeWiring.newRuntimeWiring().scalar(Scalars.graphQLObjectScalar("typeN‌​ame")). Mind you, in the 2nd and the 3rd example Scalars is io.leangen.graphql.util.Scalars not graphql.Scalars. Or just copy the SPQR code into your own class.Ramakrishna
Never knew GraphQL-SPQR existed, I'm using Code-first approach, where I've a schema.graphqls file which holds my type/api definition. Do you know how does that fit into my approach? Here is another question i asked yesterday: #47677640Descry
@Descry If you have a schema in a file, that's a schema-first approach. And I've given you the exact literal code you need to add. I can't help you further. You seem to need some more reading of the docs first.Ramakrishna
Where do you guys declare this class. I follow the example of graphql-java.readthedocs.io/en/latest/scalars.html where public static class EmailScalar is declared but the compiler fails because it is not allowed to just declare a static class anywhere. I cannot find the explaination where to declare this class actuallyGaelan
@Gaelan It's an instance of GraphQLScalarType, not a class. And who says it needs to be static?Ramakrishna
C
0

In code first approach (SPQR v0.9.6) adding @GraphQLScalar is enough. Or, as alternative, add scalar definition to GraphQLSchemaGenerator:

new GraphQLSchemaGenerator()
.withScalarMappingStrategy(new MyScalarStrategy())

And define MyScalarStrategy:

class MyScalarStrategy extends DefaultScalarStrategy {

@Override
public boolean supports(AnnotatedType type) {
  return super.supports(type) || GenericTypeReflector.isSuperType(MyScalarStrategy.class, type.getType());
}
}
Chorography answered 18/4, 2018 at 13:16 Comment(0)
M
0

add dependency in your pom file

 <dependency>
  <groupId>com.graphql-java</groupId>
  <artifactId>graphql-java-extended-scalars</artifactId>
  <version>21.0</version>
</dependency>

then write a class to register scalar Component

@Configuration

public class ScalarRegister {

   @Bean
    public RuntimeWiring.Builder addLongScalar(RuntimeWiring.Builder builder) {
        return builder.scalar(ExtendedScalars.GraphQLLong);
    }

}

Then, you can use the Long Scalar, which means the Long type. Several scalar types are available, including GraphQLChar, GraphQLLong, GraphQLBigInteger, Currency, Url, Json, and LocalTime. from creating beans you can extend the scalars

Mnemonic answered 27/12, 2023 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.