3

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.

1 Answer 1

3

The issue can be resolved declaring correspond scalar type in graphqls file scalar LocalDate.

So schema.graphqls looks like:

scalar LocalDate

type Query {
    bookById(id: ID): Book
}

type Book {
    id: ID
    name: String
    pageCount: Int
    authors: [Author]!
    productionDate: LocalDate
}

type Author {
    id: ID
    firstName: String
    lastName: String
}

The fix is published to the git also.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.