Binds a custom GraphQL scalar to a public static final GraphQLScalarType constant on the consumer’s classpath. Graphitron reflects on the constant to recover the Java type that input records, service parameters, and Field<X> projections bind to, and registers the constant on the synthesized schema so the consumer’s buildSchema hook does not have to wire it.
SDL signature
directive @scalarType(scalar: String!) on SCALAR
Parameters
| Name | Type | Description |
|---|---|---|
|
|
Fully-qualified Java reference of the form |
Canonical example
scalar BigDecimal
@scalarType(scalar: "graphql.scalars.ExtendedScalars.GraphQLBigDecimal")
type Invoice @table(name: "invoice") {
amount: BigDecimal!
}
The generator produces an input record with a java.math.BigDecimal component, a Field<BigDecimal> projection for SELECT paths, and registers ExtendedScalars.GraphQLBigDecimal via .additionalType(…) on the synthesized schema. Consumer code does not need to wire the scalar in its buildSchema hook.
Resolution order
Graphitron’s scalar resolver recognises two implicit paths plus the directive:
-
Spec built-ins.
Int,Float,String,Boolean,IDresolve through a closed table baked into the resolver.@scalarTypeon a spec built-in name is a hard validation error. -
Federation-namespaced scalars (e.g.
_FieldSet) are auto-wired when the SDL declares an Apollo Federation@link; do not redeclare them with@scalarType. -
@scalarType(scalar:)directive. The single explicit binding path for every other scalar; point it at a library constant (scalar UUID @scalarType(scalar: "graphql.scalars.ExtendedScalars.UUID")) or your own (scalar BigDecimal @scalarType(scalar: "com.example.Scalars.MONEY")).
A non-spec, non-federation scalar with no @scalarType is unresolved and the build fails with an error naming @scalarType(scalar:) as the fix. There is no silent fallback to Object.
Migration
Consumers upgrading to the resolver-driven additional-type registration must remove manual .additionalType(ExtendedScalars.GraphQLBigDecimal) (or other graphitron-resolved scalar constant) calls from their buildSchema(…) hooks. graphql-java’s GraphQLSchema.Builder.additionalType rejects duplicate type names at build time, so leaving the manual call in turns the upgrade into a SchemaProblem rather than silent tolerance.
Constraints
-
@scalarTypeis only valid onscalardeclarations. Applying it to a spec built-in (Int,Float,String,Boolean,ID) raises a directive-conflict validation error: the GraphQL spec and graphql-java already bind these names. -
The referenced class must be on the codegen classpath (
<project>/target/classes, every reactor sibling’starget/classes, or a declared dependency). Classes from<plugin><dependencies>are not visible. -
The referenced field must be
public static, non-null at code generation, and assignable tographql.schema.GraphQLScalarType. Validation errors name the specific mismatch (FieldNotFound,FieldNotAccessible,NullAtCodegen,NotAScalarType). -
The constant’s
Coercing<I, O>must declare concrete type parameters. A rawCoercingdeclaration, aCoercing<Object, Object>declaration, or an anonymous-class declaration whoseIresolves toObjectproduces aCoercingErasedrejection with a per-arm hint (extract anonymous class, declare concrete parameters, etc.).
Editor support
The graphitron LSP completes @scalarType(scalar: |) on a scalar X declaration from the GraphQLScalarType constants scanned off the codegen classpath (your own and any library’s), preferring one whose field name matches X when it exists. Diagnostics surface malformed references (no dot) and unknown classes (FQN whose class part is not on the compile classpath scan) inline; field-level failures (FieldNotFound, CoercingErased, etc.) surface during the build.
See also
-
The graphql-java-extended-scalars project: graphql-java-extended-scalars for ready-made
GraphQLScalarTypeconstants coveringBigDecimal,DateTime,UUID, and similar.