Reactive GraphQL

Viewed 2173

Trying to implement reactive graphql and running into some issues.

pom dependencies,

<dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphql-kickstart-spring-boot-starter-webflux</artifactId>
            <version>7.0.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.graphql-java-kickstart/graphql-kickstart-spring-boot-starter-tools -->
        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphql-kickstart-spring-boot-starter-tools</artifactId>
            <version>7.0.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.graphql-java-kickstart/graphiql-spring-boot-starter -->
        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>7.0.1</version>
        </dependency>

Schema:-

type Query {

  store(storeId: Int!): Store!

  stores: [Store!]!
}

type Store {
  storeId: Int!
  name: String!
  address: String!
  city: String!
  zip: String!
}

Resolver:-

@Component
public class StoreQuery implements GraphQLQueryResolver {

    @Autowired
    private final StoreDao dao;

    public Store store(int storeId) {
        return dao.findById(storeId);
    }

    public List<Store> stores() {
        return dao.findAll();
    }

}

Here, If I return Flux or Mono, getting the following error.

 "class": "org.springframework.beans.factory.BeanCreationException",
              "msg": "Error creating bean with name 'schemaParser' defined in class path resource [graphql/kickstart/tools/boot/GraphQLJavaToolsAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [graphql.kickstart.tools.SchemaParser]: Factory method 'schemaParser' threw exception; nested exception is java.lang.ClassCastException: class graphql.kickstart.tools.ParameterizedTypeImpl cannot be cast to class java.lang.Class (graphql.kickstart.tools.ParameterizedTypeImpl is in unnamed module of loader 'app'; java.lang.Class is in module java.base of loader 'bootstrap')",


  "class": "java.lang.ClassCastException",
                  "msg": "class graphql.kickstart.tools.ParameterizedTypeImpl cannot be cast to class java.lang.Class (graphql.kickstart.tools.ParameterizedTypeImpl is in unnamed module of loader 'app'; java.lang.Class is in module java.base of loader 'bootstrap')",

So, trying to return as List.

But converting Flux to List using blocking calls also throwing error,

public List<Store> findAll() {
        return Flux.from(storeCollection.find()).collectList().block();
    }

Here, getting the error below.

Exception while fetching data (/stores) : block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-kqueue-2

Using graphiql for testing.

http://localhost:8089/graphiql

2 Answers

As the error suggests, you can't use blocking operation in non-blocking webflux.

public Flux<Store> findAll() {
    return Flux.fromIterable(storeCollection.find());
    or
    return Flux.fromStream(storeCollection.find());
}

You can't use blocking operation in non-blocking webflux. If you use kickstart v.7.0.1 you should return CompletableFuture

public CompletableFuture<List<Store>> findAll() {
    return Flux.fromIterable(dao.findAll())
            .collectList()
            .toFuture();
}
Related