Skip to content

Adding Custom Scalars

It is easy to add a custom scalar type in the DGS framework: Create a class that implements the graphql.schema.Coercing interface and annotate it with the @DgsScalar annotation. Also make sure the scalar type is defined in your [GraphQL] schema!

For example, this is a simple LocalDateTime implementation:

@DgsScalar(name="DateTime")
public class DateTimeScalar implements Coercing<LocalDateTime, String> {
    @Override
    public String serialize(Object dataFetcherResult) throws CoercingSerializeException {
        if (dataFetcherResult instanceof LocalDateTime) {
            return ((LocalDateTime) dataFetcherResult).format(DateTimeFormatter.ISO_DATE_TIME);
        } else {
            throw new CoercingSerializeException("Not a valid DateTime");
        }
    }

    @Override
    public LocalDateTime parseValue(Object input) throws CoercingParseValueException {
        return LocalDateTime.parse(input.toString(), DateTimeFormatter.ISO_DATE_TIME);
    }

    @Override
    public LocalDateTime parseLiteral(Object input) throws CoercingParseLiteralException {
        if (input instanceof StringValue) {
            return LocalDateTime.parse(((StringValue) input).getValue(), DateTimeFormatter.ISO_DATE_TIME);
        }

        throw new CoercingParseLiteralException("Value is not a valid ISO date time");
    }

    @Override
    public Value valueToLiteral(@NotNull Object input) {
        return new StringValue(this.serialize(input));
    }
}

Schema:

scalar DateTime

Important

If you are Building GraphQL Queries for Tests, make sure to pass your custom scalars in GraphQLQueryRequest constructor as descibred in Scalars in DGS Client

Registering Custom Scalars

In more recent versions of graphql-java (>v15.0) some scalars, most notably the Long scalar, are no longer available by default. These are non-standard scalars that are difficult for clients (e.g. JavaScript) to handle reliably. As a result of the deprecation, you will need to add them explicitly, and to do this you have a few options.

Tip

Go to the graphql-java-extended-scalars project page to see the full list of scalars supported by this library. There you will also find examples of the scalars used in both schemas as well as example queries.

Automatically Register Scalar Extensions via graphql-dgs-extended-scalars

The DGS Framework, as of version 3.9.2, has the graphql-dgs-extended-scalars module. This module provides an auto-configuration that will register automatically the scalar extensions defined in the com.graphql-java:graphql-java-extended-scalars library. To use it you need to...

  1. Add the com.netflix.graphql.dgs:graphql-dgs-extended-scalars dependency to your build. If you are using the DGS BOM you don't need to specify a version for it, the BOM will recommend one.
  2. Define the scalar in your schema

Other mapping available on extended scalars doc

The graphql-java-extended-scalars module offers a few knobs you can use to turn off registration.

Property Description
dgs.graphql.extensions.scalars.time-dates.enabled If set to false, it will not register the DateTime, Date, and Time scalar extensions.
dgs.graphql.extensions.scalars.objects.enabled If set to false, it will not register the Object, Json, Url, and Locale scalar extensions.
dgs.graphql.extensions.scalars.numbers.enabled If set to false, it will not register all numeric scalar extensions such as PositiveInt, NegativeInt, etc.
dgs.graphql.extensions.scalars.chars.enabled If set to false, it will not register the GraphQLChar extension.
dgs.graphql.extensions.scalars.enabled If set to false, it will disable automatic registration of all of the above.

Important

Are you using the code generation Gradle Plugin?

The graphql-java-extended-scalars module doesn't modify the behavior of such plugin, you will need to explicit define the type mappings. For example, let's say we want to use both the Url and PositiveInt Scalars. You will have to add the mapping below to your build file.

generateJava {
    typeMapping = [
        "Url" : "java.net.URL",
        "PositiveInt" : "java.lang.Integer"
    ]
}
generateJava {
    typeMapping = mutableMapOf(
        "Url" to "java.net.URL",
        "PositiveInt" to "java.lang.Integer"
    )
}

Testing in Java using graphql-dgs-extended-scalars

Don't forget to provide DgsExtendedScalarsAutoConfiguration.class when testing.

@SpringBootTest(classes = {DgsAutoConfiguration.class, DgsExtendedScalarsAutoConfiguration.class})
class Test {
...

Register Scalar Extensions via DgsRuntimeWiring

You can also register the Scalar Extensions manually. To do so you need to...

  1. Add the com.graphql-java:graphql-java-extended-scalars dependency to your build. If you are using the DGS BOM you don't need to specify a version for it, the BOM will recommend one.
  2. Define the scalar in your schema
  3. Register the scalar.

Here is an example of how you would set that up:

Schema:

scalar Long
You can register the Long scalar manually with the DGS Framework as shown here:
@DgsComponent
public class LongScalarRegistration {
    @DgsRuntimeWiring
    public RuntimeWiring.Builder addScalar(RuntimeWiring.Builder builder) {
        return builder.scalar(Scalars.GraphQLLong);
    }
}