How should I configure the ObjectMapper so that it...
# troubleshoot
a
How should I configure the ObjectMapper so that it can deserialize
Entity
in
SearchQueryResponse
of a GraphQL search request? I got the following exception when trying to turn the code below it. I used the auto generated graphql client code and I confirmed that the raw response string the client received is correct.
Copy code
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.linkedin.datahub.graphql.generated.Entity (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
Copy code
final SearchInput searchInput =
        SearchInput.builder()
            .setType(EntityType.DATASET)
            .setQuery("")
            .setStart(0)
            .setCount(10)
            .build();
    final SearchQueryRequest searchQueryRequest =
        SearchQueryRequest.builder().setInput(searchInput).build();

    GraphQLResponseProjection graphQLResponseProjection =
        new SearchResultsResponseProjection()
            .start()
            .count()
            .total()
            .searchResults(
                new SearchResultResponseProjection()
                    .entity(new EntityResponseProjection().urn().type()));

    GraphQLRequest graphQLRequest =
        new GraphQLRequest(searchQueryRequest, graphQLResponseProjection);
    final SearchQueryResponse searchQueryResponse =
        getRestTemplate()
            .exchange(
                URI.create(GRAPHQL_ENDPOINT),
                <http://HttpMethod.POST|HttpMethod.POST>,
                createHttpEntity(graphQLRequest),
                SearchQueryResponse.class)
            .getBody();

    System.out.println(searchQueryResponse.search());
@green-football-43791 @bulky-soccer-26729
i
Hey Jinlin,
Entity
is a GraphQL auto-generated interface. You would need to create a custom deserialiser that routes to the appropriate class based on the
EntityType
property of the object. This is not something we have in DataHub as of right now.
o
Basically this happens because there isn't a well defined way for the ObjectMapper to route to the subtype. The way to work around this from the model side is to provide a defining attribute that determines what subtype it should be deserialized to. If you take a look at the OpenAPI models we do this with a discriminator property, but the GraphQL models don't have the equivalent so a custom deserializer that specifies what concrete type to route to is necessary.
a
Thank you @orange-night-91387 @incalculable-ocean-74010!
@incalculable-ocean-74010 @orange-night-91387, I added a custom deserializer for
Entity
and it worked great. The only problem I see is the
Dataset
class autogenerated doesn't contain the
schemaMetadata
field. I saw that it is in
entity.graphql
. https://github.com/datahub-project/datahub/blob/92192d2410f9c235a4da0a57a557160704015fbe/datahub-graphql-core/src/main/resources/entity.graphql#[…]4 But for some reason, the autogenerated Dataset class doesn't contain it. Do you guys know why?
o
schemaMetadata is a query and not a field so it doesn't get set as a property in the generated type
The codegen library treats them differently unfortunately
a
In addition to the
schemaMetadata
in this thread, we have also found the
IngestionSource
doesn't have
IngestionSourceExecutionRequests
as a field. @orange-night-91387 do you see any problem if we send a PR to set
generateParameterizedFieldsResolvers
to
false
in
build.gradle
so the response of these parameterized queries can be generated? In our testing, we only need to change
CreateViewResolver.java
because the constructor of
DatahubView
takes one more parameter with this change. FYI, @gray-airplane-39227
FYI, the author of
graphql-java-codegen
suggested this and this flag is set to false by default in
6.0.0
https://github.com/kobylynskyi/graphql-java-codegen/issues/1148
o
I don't think we would have a problem with accepting a PR with this change, we don't use the generated resolver interfaces that come from setting this to true.
a
Perfect, thank you!