Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graphql no resolver definied for interface/union - java

I have problem adding resolver using this approach in graphql:

@RestController
@RequestMapping("/api/dictionary/")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DictionaryController {
    @Value("classpath:items.graphqls")
    private Resource schemaResource;
    private GraphQL graphQL;
    private final DictionaryService dictionaryService;

    @PostConstruct
    public void loadSchema() throws IOException {
        File schemaFile = schemaResource.getFile();
        TypeDefinitionRegistry registry = new SchemaParser().parse(schemaFile);
        RuntimeWiring wiring = buildWiring();
        GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(registry, wiring);
        graphQL = GraphQL.newGraphQL(schema).build();
    }

private RuntimeWiring buildWiring() {
    DataFetcher<List<DictionaryItemWithParentDto>> fetcher6 = dataFetchingEnvironment -> dictionaryService.getClaimSubType();

        return RuntimeWiring.newRuntimeWiring()
                .type("Query", typeWriting ->
                   typeWriting
                    .dataFetcher("getClaimSubType", fetcher6)
                    )
                .build();
    }


public List<DictionaryItemWithParentDto> getClaimSubType() {
    return dictionaryService.getClaimSubType();
   }
  }

items.graphqls file content:

type Query {
    getClaimSubType: [DictionaryItemWithParentDto]
}

type DictionaryItemWithParentDto {
    code: String!
    name: String
    parents: [DictionaryItemDto]
}

type DictionaryItemDto {
    code: String!
    name: String
    description: String
}

In java I have Vehicle interface and two classes that implement it: Airplane and Car. When i add to schema this line:

union SearchResult = Airplane | Car

I get following error:

There is no type resolver defined for interface / union 'Vehicle' type, There is no type resolver defined for interface / union 'SearchResult' type]}

I am not sure how to handle it.

If instead i add:

interface Vehicle {
    maxSpeed: Int
}

type Airplane implements Vehicle {
    maxSpeed: Int
    wingspan: Int
}

type Car implements Vehicle {
    maxSpeed: Int
    licensePlate: String
}

I get following error:

errors=[There is no type resolver defined for interface / union 'Vehicle' type]

How can i handle these errors using my approach ? Is there another approach to handle it?

Edit

Adding these lines of code fix the issue partway i guess:

TypeResolver t =  new TypeResolver() {
    @Override
    public GraphQLObjectType getType(TypeResolutionEnvironment env) {
        Object javaObject = env.getObject();
        if (javaObject instanceof Car) {
            return env.getSchema().getObjectType("Car");
        } else if (javaObject instanceof Airplane) {
            return env.getSchema().getObjectType("Airplane");
        } else {
            return env.getSchema().getObjectType("Car");
        }
    }
};

And adding to RuntimeWiring builder this:

            .type("Vehicle", typeWriting ->
                    typeWriting
                            .typeResolver(t)
            )


    @PostMapping("getVehicle")
    public ResponseEntity<Object> getVehicleMaxSpeed(@RequestBody String query) 
   {
        ExecutionResult result = graphQL.execute(query);
        return new ResponseEntity<Object>(result, HttpStatus.OK);
    }

When asking for:

query {
    getVehicle(maxSpeed: 30) {
        maxSpeed

    }
}

I get the maxSpeed but when i add wingspan i get an error

Field 'wingspan' in type 'Vehicle' is undefined @ 'getVehicle/wingspan'",

I added

getVehicle(maxSpeed: Int): Vehicle

To the graphqls file. I thought that polymorphism would work here.

like image 378
tryingHard Avatar asked Jan 18 '19 10:01

tryingHard


People also ask

Can an interface implement another interface GraphQL?

Only types can implement an interface. An interface cannot implement another interface. You can see the syntax for interfaces defined here, which distinctly lacks the ImplementsInterfaces definition shown here.

What is resolver in GraphQL?

A resolver is a function that's responsible for populating the data for a single field in your schema. It can populate that data in any way you define, such as by fetching data from a back-end database or a third-party API.

What is __ Typename in GraphQL?

The __typename field returns the object type's name as a String (e.g., Book or Author ). GraphQL clients use an object's __typename for many purposes, such as to determine which type was returned by a field that can return multiple types (i.e., a union or interface).


1 Answers

Adding these lines of code fix the issue:

TypeResolver t =  new TypeResolver() {
    @Override
    public GraphQLObjectType getType(TypeResolutionEnvironment env) {
        Object javaObject = env.getObject();
        if (javaObject instanceof Car) {
            return env.getSchema().getObjectType("Car");
        } else if (javaObject instanceof Airplane) {
            return env.getSchema().getObjectType("Airplane");
        } else {
            return env.getSchema().getObjectType("Car");
        }
    }
};

And adding to RuntimeWiring builder this:

            .type("Vehicle", typeWriting ->
                    typeWriting
                            .typeResolver(t)
            )


    @PostMapping("getVehicle")
    public ResponseEntity<Object> getVehicleMaxSpeed(@RequestBody String query) 
   {
        ExecutionResult result = graphQL.execute(query);
        return new ResponseEntity<Object>(result, HttpStatus.OK);
    }

When asking for:

query {
    getVehicle(maxSpeed: 30) {
        maxSpeed

    }
}

I get the maxSpeed but when i add wingspan i get an error

Field 'wingspan' in type 'Vehicle' is undefined @ 'getVehicle/wingspan'",

I added

getVehicle(maxSpeed: Int): Vehicle

To the graphqls file. I thought that polymorphism would work here.

If i want fields from subclasses i can ask for them like that:

query {
    getVehicle(maxSpeed: 10) {
        maxSpeed
        ... on Airplane {
        wingspan
      }
        ... on Car {
        licensePlate
      }
    }
}
like image 145
tryingHard Avatar answered Sep 28 '22 10:09

tryingHard