Search code examples
graphqlquarkussmallrye

Quarkus Typesafe GraphQL client: add argument to filter


I am following the GraphQL client guide: https://quarkus.io/guides/smallrye-graphql-client

Right now the microprofile-graphql-client-quickstart is only executing a query returning all films:

{
  allFilms {
    films {
      title
      planetConnection {
        planets {
          name
        }
      }
    }
  }
}

Link to run on it on GraphiQL


I was wondering how you get only one film using a parameter.

If I got the model right you can do a filter using filmID or id like this:

{
  film(filmID: 1) {
    title
    planetConnection {
      planets {
        name
      }
    }
  }
}

Link to run on it on GraphiQL

For the dynamic client, I was able to do something like this (new method in the StarWarsResource class next to the getAllFilmsUsingDynamicClient() method

    @GET
    @Path("/dynamic/{filmID}")
    @Blocking
    public Film getOneFilmUsingDynamicClient(@PathParam(value = "filmID") String filmID) throws Exception {
        Document query = document(
                operation(
                        field("film",
                                args(arg("filmID", filmID)),
                                    field("id"),
                                    field("title"),
                                    field("planetConnection",
                                            field("planets",
                                                    field("name")
                                            )
                                    )
                        )
                )
        );
        Response response = dynamicClient.executeSync(query);
        System.out.println(response.getData());
        // Either work with the data as a JsonObject, or, as we show here,
        // translate it into an instance of the corresponding model class
        return response.getObject(Film.class, "film");
    }

But I was not able to do the same with the typesafe client.

I modified the StarWarsClientApi class to add a new method to query one film by filmID:

@GraphQLClientApi(configKey = "star-wars-typesafe")
public interface StarWarsClientApi {

    FilmConnection allFilms();

    Film film(String filmID);

}

Which should work according to: https://github.com/smallrye/smallrye-graphql/issues/465#issuecomment-764791100

But I get following error:

GraphQlClientException: errors from service
errors:
- Error{message=Variable "$filmID" of type "String" used in position expecting type "ID"., locations=[{line=1, column=12}, {line=1, column=44}], path=null, extensions={}})
    at io.smallrye.graphql.client.impl.typesafe.ResultBuilder.readErrors(ResultBuilder.java:111)
    at io.smallrye.graphql.client.impl.typesafe.ResultBuilder.read(ResultBuilder.java:67)
    at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientProxy.executeSingleResultOperationOverHttpSync(VertxTypesafeGraphQLClientProxy.java:178)
    at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientProxy.invoke(VertxTypesafeGraphQLClientProxy.java:160)
    at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientBuilder.invoke(VertxTypesafeGraphQLClientBuilder.java:231)
    at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientBuilder.lambda$build$0(VertxTypesafeGraphQLClientBuilder.java:191)
    at jdk.proxy8/jdk.proxy8.$Proxy53.film(Unknown Source)
    at org.acme.microprofile.graphql.client.StarWarsClientApi_fmoJ88eWF_bFzf8V-OFbJxgHC7c_Synthetic_ClientProxy.film(Unknown Source)
    at org.acme.microprofile.graphql.client.StarWarsResource.getOneFilmUsingTypesafeClient(StarWarsResource.java:67)
    at org.acme.microprofile.graphql.client.StarWarsResource$quarkusrestinvoker$getOneFilmUsingTypesafeClient_cd5374dc70c515863cb7e9d576cfe84970b78894.invoke(Unknown Source)
    at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
    at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
    at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
    at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:599)
    at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)

Solution

  • In the client API, you need to declare the filmID argument as a numeric ID, like this:

    Film film(@Id int filmID);