graphql-spring-boot icon indicating copy to clipboard operation
graphql-spring-boot copied to clipboard

Webflux ClassCastException for Flux response type

Open Sam-Kruglov opened this issue 5 years ago • 5 comments

If a resolver has Flux<...> return type and schema has [...] return type then it will crash on this line:

com/graphql-java-kickstart/graphql-java-tools/5.7.1/graphql-java-tools-5.7.1-sources.jar!/com/coxautodev/graphql/tools/TypeClassMatcher.kt:78

is ListType -> {
   // realType is ParameterizedTypeImpl but isListType is false
    if (realType is ParameterizedType && isListType(realType, potentialMatch)) {
        match(potentialMatch, graphQLType.type, realType.actualTypeArguments.first())
   // cast exception
    } else if ((realType as Class<*>).isArray) {
        match(potentialMatch, graphQLType.type, realType.componentType)
    } else {
        throw error(potentialMatch, "Java class is not a List or generic type information was lost: $realType")
    }
}

It works if such query is actually a subscription of return type ... and the resolver of Publisher<...>

Sam-Kruglov avatar Jan 11 '20 19:01 Sam-Kruglov

I mentioned in https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/326 why I think it's not a good idea to write all Flux resolvers as subscriptions

Sam-Kruglov avatar Jan 12 '20 08:01 Sam-Kruglov

I switched to WebFlux recently. Previously GraphQL with Spring MVC was working fine.

If I understand correctly, I have to do something like this

schema {
    query: Query
    subscription: Subscription
}

type Query {
}
type Subscription {
    search: Doc!
}
type Doc {
    uri: String!
}

And then I have a Subscription service like this

@Service
public class Subscription implements GraphQLSubscriptionResolver {

    private IndexService indexService;

    public Subscription(IndexService indexService) {
        this.indexService = indexService;
    }

    public Publisher<Doc> search() {
        return indexService.findAll();
    }
}

But I keep getting this exception

org.springframework.core.codec.CodecException: Type definition error: [simple type, class graphql.execution.reactive.CompletionStageMappingPublisher]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class graphql.execution.reactive.CompletionStageMappingPublisher and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.LinkedHashMap["data"])

Any ideas?? :( :( :(

AlexTo avatar Jan 28 '20 06:01 AlexTo

Maybe you didn't include graphql kickstart webflux dependency

Sam-Kruglov avatar Jan 28 '20 07:01 Sam-Kruglov

I have the dependencies as follows

        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java</artifactId>
            <version>2020-01-24T03-11-44-8a5fe91</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphql-kickstart-spring-boot-starter-tools</artifactId>
            <version>6.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphql-kickstart-spring-boot-starter-webflux</artifactId>
            <version>6.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java-kickstart</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.7.1</version>
        </dependency>

AlexTo avatar Jan 28 '20 07:01 AlexTo

Maybe you're using mvc and webflux, where mvc wins. See example project somewhere in this repository. Or my "bank" project in api module

Sam-Kruglov avatar Jan 28 '20 08:01 Sam-Kruglov