americanexpress / nodes

A GraphQL JVM Client - Java, Kotlin, Scala, etc.
Apache License 2.0
307 stars 70 forks source link

Exception Cannot deserialize instance of `Class` out of START_ARRAY token #26

Closed davidegph closed 6 years ago

davidegph commented 6 years ago

Hi,

I am trying to use Nodes to query my GraphQL server; this is the query,

GraphQLTemplate graphQLTemplate = new GraphQLTemplate();

GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
            .url("http://localhost:32806/graphql")
            .arguments(new Arguments("dishes", new Argument<String>("chef_id", "chef_1")), new Arguments("dishes", new Argument<String>("name", "Pizza")))
            .request(Dish.class)
            .build();
System.out.println(requestEntity.getRequest());
GraphQLResponseEntity<Dish> responseEntity = graphQLTemplate.query(requestEntity, Dish.class);

This is the model,

@GraphQLProperty(name="dishes", arguments = {@GraphQLArgument(name = "chef_id"), @GraphQLArgument(name = "dish_id")})
public class Dish
{

    private String chef_id;
    private String dish_id;
    private String name;
    private String description;

...getters and setters...
}

This is the schema,

dishes(chef_id: String! dish_id: String name: String limit: Int = 100 offset: Int = 0 columnToSort: SortDishColumn = NAME order: OrderBy = DESCENDING): [Dish]!

The query that Nodes generates is,

query { dishes (chef_id:"chef_1", name:"Pizza") { chef_id name description dish_id } }

The query does work when used with graphiql, and it is exactly what I am expecting from it. However, the code throws an exception every time,

Exception in thread "main" GraphQLException{message='null', status='200', description='Cannot deserialize instance of `org.[... my addition].models.Dish` out of START_ARRAY token
 at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: io.aexp.nodes.graphql.Wrapper["data"])', errors=null}
    at io.aexp.nodes.graphql.Fetch.send(Fetch.java:84)
    at io.aexp.nodes.graphql.GraphQLTemplate.execute(GraphQLTemplate.java:83)
    at io.aexp.nodes.graphql.GraphQLTemplate.query(GraphQLTemplate.java:42)

Any idea of what I am doing wrong?

Thank you for your help.

chemdrew commented 6 years ago

Hi @davidegph,

Great question, this is actually something I need to update the docs with as it's a common problem that isn't very clear. Fortunately, there is a simple way to handle this!

public class Dish {
    private String chef_id;
    private String dish_id;
    private String name;
    private String description;

...getters and setters...
}
public class Dishes {
  @GraphQLArguments({
    @GraphQLArgument(name = "chef_id"),
    @GraphQLArgument(name = "dish_id")
    @GraphQLArgument(name = "name")
  })
  private List<Dish> dishes;

...getter and setter...
}
GraphQLTemplate graphQLTemplate = new GraphQLTemplate();

GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
            .url("http://localhost:32806/graphql")
            .arguments(new Arguments("dishes", new Argument<String>("chef_id", "chef_1"), new Argument<String>("name", "Pizza")))
            .request(Dishes.class)
            .build();
System.out.println(requestEntity.getRequest());
GraphQLResponseEntity<Dishes> responseEntity = graphQLTemplate.query(requestEntity, Dishes.class);

Hope this helps!

davidegph commented 6 years ago

Thank you for your help Andrew! I was able to query my graphql schema thanks to your suggestions.

mario-martinez-se commented 5 years ago

Hi, I've been trying this example and for some reason it throws a NPE. This is the code I am trying (copied from here with small modifications as I am running it from groovy instead of Java)

public class Dish {
    String chef_id;
    String dish_id;
    String name;
    String description;
}

public class Dishes {
  @GraphQLArguments([
    @GraphQLArgument(name = "chef_id"),
    @GraphQLArgument(name = "dish_id"),
    @GraphQLArgument(name = "name")
  ])
  List<Dish> dishes;
}

GraphQLTemplate graphQLTemplate = new GraphQLTemplate();

GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
            .url("http://localhost:32806/graphql")
            .arguments(new Arguments("dishes", new Argument<String>("chef_id", "chef_1"), new Argument<String>("name", "Pizza")))
            .request(Dishes.class)
            .build();
System.out.println(requestEntity.getRequest());
GraphQLResponseEntity<Dishes> responseEntity = graphQLTemplate.query(requestEntity, Dishes.class);

When running this, I get this NPE:

java.lang.NullPointerException
at io.aexp.nodes.graphql.GraphQLRequestEntity.isProperty(GraphQLRequestEntity.java:201)
at io.aexp.nodes.graphql.GraphQLRequestEntity.getChildren(GraphQLRequestEntity.java:302)
at io.aexp.nodes.graphql.GraphQLRequestEntity.setPropertiesFromClass(GraphQLRequestEntity.java:153)
at io.aexp.nodes.graphql.GraphQLRequestEntity.<init>(GraphQLRequestEntity.java:58)
at io.aexp.nodes.graphql.GraphQLRequestEntity$RequestBuilder.build(GraphQLRequestEntity.java:379)
at io.aexp.nodes.graphql.GraphQLRequestEntity$RequestBuilder$build$1.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)

All I had to change in order to adapt it from Java to groovy was removing the private and getters and setters. Also I changed @GraphQLArguments({...}) with @GraphQLArguments([]). Any idea what am I doing wrong?

debdiptahalder-4tigo commented 5 years ago

Hi the above solution is not working for me. I am still getting the same issue . I am not able to understand what to send in the arguments if the API does not take any arguments.