I've configured GraphQL in spring boot application which uses java 17.
To start application you need gradle bootRun.
To try GrapqQL request you can use curl:
curl -X POST http://localhost:8085/graphql \
-H "Content-Type: application/json" \
-d '{"query":"query {\n bookById(id: \"book-1\"){\n id\n name\n pageCount\n productionDate\n authors {\n id\n firstName\n lastName\n }\n }\n}"}'
The current configuration doesn't use custom type LocalDate and no date formatting with pattern"dd/MM/yyyy".
The GraphQL configuration schema.graphqls
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
authors: [Author]!
productionDate: String
# productionDate: LocalDate
}
type Author {
id: ID
firstName: String
lastName: String
}
requires productionDate: LocalDate (in the line 10). The custom java configuration is managed in the ScalarConfiguration.java following spring-boot,
package com.graphqljava.tutorial.bookDetails;
import graphql.language.StringValue;
import graphql.schema.*;
import org.springframework.boot.autoconfigure.graphql.GraphQlSourceBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
@Configuration(proxyBeanMethods = false)
public class ScalarConfiguration {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Bean
public GraphQLScalarType dateScalar() {
return GraphQLScalarType.newScalar()
.name("LocalDate")
.description("Java 8 LocalDate as scalar.")
.coercing(new Coercing<Object, Object>() {
@Override
public String serialize(final Object dataFetcherResult) {
if (dataFetcherResult instanceof LocalDate) {
return formatter.format((LocalDate) dataFetcherResult);
} else {
throw new CoercingSerializeException("Expected a LocalDate object.");
}
}
@Override
public LocalDate parseValue(final Object input) {
try {
if (input instanceof String) {
return LocalDate.parse((String) input, formatter);
} else {
throw new CoercingParseValueException("Expected a String");
}
} catch (DateTimeParseException e) {
throw new CoercingParseValueException(String.format("Not a valid date: '%s'.", input), e
);
}
}
@Override
public LocalDate parseLiteral(final Object input) {
if (input instanceof StringValue) {
try {
return LocalDate.parse(((StringValue) input).getValue(), formatter);
} catch (DateTimeParseException e) {
throw new CoercingParseLiteralException(e);
}
} else {
throw new CoercingParseLiteralException("Expected a StringValue.");
}
}
}).build();
}
// https://docs.spring.io/spring-graphql/docs/1.1.0-RC1/reference/html/#execution-graphqlsource-runtimewiring-configurer
@Bean
RuntimeWiringConfigurer runtimeWiringConfigurer() {
GraphQLScalarType scalarType = dateScalar();
return wiringBuilder -> wiringBuilder.scalar(scalarType);
}
/*
// https://docs.spring.io/spring-graphql/docs/1.1.0-RC1/reference/html/#execution-graphqlsource
@Bean
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
GraphQLScalarType scalarType = dateScalar();
return (builder) ->
builder.configureGraphQl(graphQlBuilder ->
graphQlBuilder.executionIdProvider((query, operationName, context) -> null));
}
*/
}
so runtimeWiringConfigurer loads correctly, but LocalDate doesn't work in my schema.graphqls and I'm looking for help and solution with described issue.
P.S.
- The git source is here.
- I've detected there similar questions, but their answers didn't help me properly. In current question I've provided git java project which can be fixed to make working it with
LocalDate.