Skip to content
This repository has been archived by the owner on Dec 19, 2023. It is now read-only.

Configure GraphQLServlet object mapper #32

Closed
miguelaferreira opened this issue Sep 13, 2017 · 7 comments
Closed

Configure GraphQLServlet object mapper #32

miguelaferreira opened this issue Sep 13, 2017 · 7 comments

Comments

@miguelaferreira
Copy link

miguelaferreira commented Sep 13, 2017

It's possible to configure the object mapper used by the GraphQLServlet via a custom implementation of the (functional) interface ObjectMapperConfigurer (see graphql-java-kickstart/graphql-java-servlet@8f55785).

I would expect it to be possible to register a bean of such implementation in the application context and have it injected in the GraphQLServlet. However this doesn't seem to be possible yet.

Here's what I'm trying to do:

@SpringBootApplication
public class Application {

(...)

    @Bean
    ObjectMapperConfigurer objectMapperConfigurer() {
        return (ObjectMapper mapper) -> mapper.registerModule(new JavaTimeModule());
    }

(...)

}

Is this something that needs to be implemented yet? Or am I going about it the wrong way?

@apottere
Copy link
Collaborator

Are you using 3.9.0? I released this change yesterday which should support that: fff13ab

@miguelaferreira
Copy link
Author

miguelaferreira commented Sep 13, 2017

Yes, I am. I've just debugged the bootstrapping of the application and I do see that my configuration is being applied to the object mapper. So, answering my own question, configuration works just fine. I'll close the issue now and if relevant I'll post here (for reference) how I solved my problem.

@miguelaferreira
Copy link
Author

miguelaferreira commented Sep 13, 2017

A bit more debugging shows that the object mapper used to deserialise inputs from mutations is not the same as the one I configured via a bean in the Application class.

When I debug the bootstrapping of the application I see that the module JavaTimeModule is added to a object mapper that already contains the Jdk8Module (as expected).

Before my configuration is applied:

before-configuration

After my configuration is applied:

after-configuration

However, when handling the input of a mutation the object mapper is different (with a different memory address) and no longer has the JavaTimeModule.

handling-mutation

@miguelaferreira
Copy link
Author

miguelaferreira commented Sep 13, 2017

It seems that the object mapper that deserialises the values passed into the mutation is not the one in the servlet but instead it's the one in com.coxautodev.graphql.tools.MethodFieldResolver. java-graphql-tools also has it's own ObjectMapperConfigurer abstraction.

@miguelaferreira
Copy link
Author

miguelaferreira commented Sep 13, 2017

I've fixed my problem (deserialising LocalDateTime objects passed in as inputs to mutations) by also registering a bean to configure the object mapper used by java-graphql-tools (which I use to parse the schema definition).

So the final configuration looks like this:

@SpringBootApplication
public class Application {

(...)

    @Bean
    ObjectMapperConfigurer objectMapperConfigurer() {
        return (ObjectMapper mapper) -> mapper.registerModule(new JavaTimeModule());
    }

    @Bean
    SchemaParserOptions schemaParserOptions() {
        return SchemaParserOptions.newOptions()
                                  .objectMapperConfigurer((ObjectMapper mapper, ObjectMapperConfigurerContext context) -> mapper.registerModule(new JavaTimeModule()))
                                  .build();
    }
(...)

}

@apottere
Copy link
Collaborator

Ah, yeah. The servlet object mapper handles parsing variables and output, but the graphql-java-tools objectmapper handles marshalling the field input values to java types. It's a little wonky, but since the two libraries can be used independently I'm not sure how to make it better.

@miguelaferreira
Copy link
Author

miguelaferreira commented Sep 14, 2017

It's indeed a difficult one to solve elegantly. If the interfaces for the ObjectMapperConfigurer in both projects would align, then it would be possible to create one configuration bean that would get injected in both sides. It wouldn't be super elegant, but a least would remove the need to configure things twice.

Thanks again for being so active in giving support 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants