GraphQlScalarConfig.java
package io.slayyyyer.orders.config;
import graphql.language.IntValue;
import graphql.language.StringValue;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import graphql.schema.GraphQLScalarType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
/**
* GraphQL knows Int, Float, String, Boolean and ID. It does not know {@code Long}, but the
* schema needs one: money is stored in cents, and cents do not fit in a 32-bit Int for
* anything that is not a hobby project.
*
* <p>Without this, building the {@code GraphQlSource} fails with
* {@code There is no scalar implementation for the named 'Long' scalar type} — at startup,
* so no unit test notices it.
*/
@Configuration
public class GraphQlScalarConfig {
private static final GraphQLScalarType LONG = GraphQLScalarType.newScalar()
.name("Long")
.description("A signed 64-bit integer. Used for monetary amounts in cents.")
.coercing(new LongCoercing())
.build();
@Bean
public RuntimeWiringConfigurer longScalarWiring() {
return wiring -> wiring.scalar(LONG);
}
/**
* The single-argument coercing methods are the ones every graphql-java version still
* routes through, so implementing them keeps this independent of the exact release.
*/
static final class LongCoercing implements Coercing<Long, Long> {
@Override
public Long serialize(Object dataFetcherResult) {
return toLong(dataFetcherResult, CoercingSerializeException::new);
}
@Override
public Long parseValue(Object input) {
return toLong(input, CoercingParseValueException::new);
}
@Override
public Long parseLiteral(Object input) {
if (input instanceof IntValue intValue) {
return intValue.getValue().longValue();
}
if (input instanceof StringValue stringValue) {
try {
return Long.parseLong(stringValue.getValue());
} catch (NumberFormatException e) {
throw new CoercingParseLiteralException("Cannot parse \"" + stringValue.getValue() + "\" as a Long");
}
}
throw new CoercingParseLiteralException("Expected an integer literal for Long");
}
private static Long toLong(Object value, java.util.function.Function<String, RuntimeException> error) {
if (value instanceof Number number) {
return number.longValue();
}
if (value instanceof String text) {
try {
return Long.parseLong(text);
} catch (NumberFormatException e) {
throw error.apply("Cannot parse \"" + text + "\" as a Long");
}
}
throw error.apply("Cannot represent " + value + " as a Long");
}
}
}