Giter VIP home page Giter VIP logo

graphql-java-tools's Introduction

GraphQL Java Tools

Github Build Maven Central Discuss on GitHub

This library allows you to use the GraphQL schema language to build your graphql-java schema. Inspired by graphql-tools, it parses the given GraphQL schema and allows you to BYOO (bring your own object) to fill in the implementations. GraphQL Java Tools works well if you already have domain POJOs that hold your data (e.g. for RPC, ORM, REST, etc) by allowing you to map these "magically" to GraphQL objects.

GraphQL Java Tools aims for seamless integration with Java, but works for any JVM language. Try it with Kotlin!

We are looking for contributors!

Are you interested in improving our documentation, working on the codebase, reviewing PRs?

Reach out to us on GitHub and join the team!

Quick start

Using Gradle

Set the Kotlin version in your gradle.properties:

kotlin.version=1.8.21

Add the dependency:

compile 'com.graphql-java-kickstart:graphql-java-tools:13.1.1'

Using Maven

Set the Kotlin version in your <properties> section:

<properties>
    <kotlin.version>1.8.21</kotlin.version>
</properties>

Add the dependency:

<dependency>
    <groupId>com.graphql-java-kickstart</groupId>
    <artifactId>graphql-java-tools</artifactId>
    <version>13.1.1</version>
</dependency>

Documentation

Take a look at our documentation for more details.

Why GraphQL Java Tools?

  • Schema First: GraphQL Java Tools allows you to write your schema in a simple, portable way using the GraphQL schema language instead of hard-to-read builders in code.
  • Minimal Boilerplate: It takes a lot of work to describe your GraphQL-Java objects manually, and quickly becomes unreadable. A few libraries exist to ease the boilerplate pain, including GraphQL-Java's built-in schema-first wiring, but none (so far) do type and datafetcher discovery.
  • Stateful Data Fetchers: If you're using an IOC container (like Spring), it's hard to wire up datafetchers that make use of beans you've already defined without a bunch of fragile configuration. GraphQL Java Tools allows you to register "Resolvers" for any type that can bring state along and use that to resolve fields.
  • Generated DataFetchers: GraphQL Java Tools automatically creates data fetchers for your fields that call the appropriate method on your java class. This means all you have to do to create a new field is add the field definition to your schema and add a corresponding method on your class.
  • Type->Class Discovery: GraphQL Java Tools starts from your root objects (Query, Mutation) and, as it's generating data fetchers for you, starts to learn about the classes you use for a certain GraphQL type.
  • Class Validation: Since there aren't any compile-time checks of the type->class relationship, GraphQL Java Tools will warn you if you provide classes/types that you don't need to, as well as erroring if you use the wrong Java class for a certain GraphQL type when it builds the schema.
  • Unit Testing: Since your GraphQL schema is independent of your data model, this makes your classes simple and extremely testable.

Known Issues

Known issues are aggregated at the wiki.

graphql-java-tools's People

Contributors

acidbluebriggs avatar actions-user avatar adisesha avatar ajkerr avatar apottere avatar b4eex avatar cliedeman avatar danilo-barboza avatar dependabot[bot] avatar gipeshka avatar jdorleans avatar jhaber avatar kammerertob avatar lburja avatar marcus-nl avatar martinraison avatar mlvandijk avatar oliemansm avatar oryan-block avatar plaurina avatar renovate-bot avatar renovate[bot] avatar rideliner avatar rrva avatar setchy avatar sp00m avatar timward60 avatar varahash avatar visualage avatar vojtapol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-java-tools's Issues

Exception if Schema have more than one types having multiple implementations.

Sample code is placed here
https://github.com/gkarthics/graphql-java-tools-multiple-interface-example

In a schema, if there is only one type having two implementations its working fine.

But if there is another type object which also has two implementations like shown below,

interface FirstInterface {
  firstInterfaceValue : String
}

interface SecondInterface {
	secondInterfaceValue : String
}

type FirstImpl implements FirstInterface {
    firstInterfaceValue : String
    firstImplId: ID!
    firstImplValue: String
    dataType : DataType
}

type SecondImpl implements SecondInterface, FirstInterface {
    secondImplId: ID!
    secondImplValue: String
    secondInterfaceValue : String
    firstInterfaceValue : String
}

type ThirdImpl implements SecondInterface, FirstInterface {
    secondImplId: ID!
    secondImplValue: String
    secondInterfaceValue : String
    firstInterfaceValue : String
}

I am getting the following exception.

com.coxautodev.graphql.tools.SchemaClassScannerError: Object type 'ThirdImpl' implements a known interface, but no class was found for that type name. Please pass a class for type 'ThirdImpl' in the parser's dictionary. at com.coxautodev.graphql.tools.SchemaClassScanner.handleInterfaceOrUnionSubTypes(SchemaClassScanner.kt:183) at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:89) at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:125) at com.graphql.GraphQLEndpoint.buildSchema(GraphQLEndpoint.java:26) at com.graphql.GraphQLEndpoint.<init>(GraphQLEndpoint.java:16) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:422) at java.lang.Class.newInstance(Class.java:442) at org.eclipse.jetty.server.handler.ContextHandler$Context.createInstance(ContextHandler.java:2470) at org.eclipse.jetty.servlet.ServletContextHandler$Context.createServlet(ServletContextHandler.java:1327) at org.eclipse.jetty.servlet.ServletHolder.newInstance(ServletHolder.java:1220) at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:612) at org.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:496) at org.eclipse.jetty.servlet.ServletHolder.ensureInstance(ServletHolder.java:788) at org.eclipse.jetty.servlet.ServletHolder.prepare(ServletHolder.java:773) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:578) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1174) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1106) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) at org.eclipse.jetty.server.Server.handle(Server.java:524) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95) at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) at java.lang.Thread.run(Thread.java:745)

How can I tell which fields are requested?

I'm new to this, but managed to get up and running no probs - looks great.

I'm not sure if I'm missing something though - how am I able to know which fields have been requested? My back end is an oracle DB with potentially hundreds of different columns coming back. If the client only asks for 3, I only want to query the DB with 3 - is there an object that will give me the columns (fields) that the client has requested?

Thanks
Jason

Sub-selections on a null field should just be null, not cause errors

If a field is resolved to a null, and the query wants a sub-selection of it, all the sub-field values should also just be null, not cause errors. Yet, if I try such a thing I get an error for each of the subfields.

Here's an example:

public class LinkResolver implements GraphQLResolver<Link> {
    
    private final UserRepository userRepository;

    public LinkResolver(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User postedBy(Link link) {
        if (link.getUserId() == null) {
            return new User("", "", "", ""); // <----- this is the interesting line
        }
        return userRepository.findById(link.getUserId());
    }
}

If that line is replaced by return null, the result for a query like:

{
    allLinks {
        url
        postedBy {
           name
           email
        }
    }
}

would contain an error for each name and email for a postedBy that is null.

"Two different classes used for type" reports null class

With graphql-java-tools 3.1.2, I get an error that refers to the class null instead of the actual class:

Exception in thread "main" com.coxautodev.graphql.tools.SchemaClassScannerError: Two different classes used for type Scalar:
- class java.lang.Object:
|   return type of method public java.lang.Object com.example.GraphQLToolsErrorExample$Query.a()

- null:
|   return type of method public java.lang.String com.example.GraphQLToolsErrorExample$Query.b()
	at com.coxautodev.graphql.tools.SchemaClassScanner.handleFoundType(SchemaClassScanner.kt:208)
	at com.coxautodev.graphql.tools.SchemaClassScanner.handleFoundType(SchemaClassScanner.kt:193)
	at com.coxautodev.graphql.tools.SchemaClassScanner.handleFieldMethod(SchemaClassScanner.kt:185)
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanObjectForDictionaryItems(SchemaClassScanner.kt:177)
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:95)
	at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:107)
	at com.example.GraphQLToolsErrorExample.main(GraphQLToolsErrorExample.java:37)

Here's a simple example to reproduce:

package com.example;

import com.coxautodev.graphql.tools.GraphQLRootResolver;
import com.coxautodev.graphql.tools.SchemaParser;

public class GraphQLToolsErrorExample {
  public static class Query implements GraphQLRootResolver {
    public Object a() {
      return "a";
    }
    public String b() {
      return "b";
    }
  }
  public static void main(String... args) {
    SchemaParser.newParser()
        .schemaString("scalar Scalar type Query { a: Scalar b: Scalar}")
        .resolvers(new Query())
        .build()
        .makeExecutableSchema();
  }
}

Trying to define a customscalar in Input,

Hello everyone,

We planned to use graphql-java as backend query server. I am in mid of doing a POC with graphql-java. I have a query defined in schema. It works fine until if i use direct graphqlscalartype. But in actual usecase we have a java Map object in request. how can i match a property in to my map field using CUSTOM SCALAR concept? Below is the scenario.

schema

type Query{
	getMessageDetails(serviceContext : ServiceContext, messageDetailRqst : MessageDetailRqst) : GetMessageDetailsResp
}

input ServiceContext {
	appAccessType: String
	language: String
	addnContext: customMap
}

input MessageDetailRqst {
	category: String
	fromDate: String
}
class ServiceContext {
   private Map<String,Object> addnContext;
}

Have tried using creating a class extends graphqlscalartype and implemented coering interface. getting below error. Kindly help.

_Caused by: com.coxautodev.graphql.tools.SchemaClassScannerError: Unable to match type definition (TypeName{name='customMap'}) with java type (java.util.Map<java.lang.String, java.lang.Object>): No TypeDefinition for type name Date
	at com.coxautodev.graphql.tools.TypeClassMatcher.error(TypeClassMatcher.kt:17)
	at com.coxautodev.graphql.tools.TypeClassMatcher.match(TypeClassMatcher.kt:59)
	_

IDL Modularisation

in graphql-java a type can be extended to add more fields but graphql-java-tools doesn't honor that. Check this example project https://github.com/oexza/graphql-java-tools-test you'll find that the Query type is extended in the Internal.graphqls file but introspection shows that it actually replaces the Query instead of just adding the field.

Allow generic custom generic types as return types of methods

In class GenericType.RelativeTo, the method unwrapGenericType has a list of Java types that should be considered wrappers, and the actual type is the first type parameter. I'd like to propose making this list configurable, as it's necessary for f.e. adapting reactive-streams return values.

My personal use case was a reactive ExecutionStrategy that can fetch properties in parallel via RxJava; it works nicely (and fast), but it required modifying the above-mentioned class so that return types are recognized as the proper types.

I don't trust yet my Kotlin knowledge to create a PR that implements this, and while admittedly it's a relatively niche requirement, it does make sense to have that type list generic.

Support for partial implemented schemas

When I'm just getting started, I personally find it useful to write out the schema and then run graphiql against it to test out queries. Unfortunately I need to write data classes for the entire schema in order to even start the application, which makes this very tedious. Being able to configure it to not care about this would be helpful so that it can be built a piece at a time.

Example project fails to start

It seems that the example project doesn't start after a fresh clone, and I'm wondering if I'm missing a step?

I'm seeing this stack trace at launch:

...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLSchema' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLJavaToolsAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLSchema' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schemaParser' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLJavaToolsAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.coxautodev.graphql.tools.SchemaParser]: Factory method 'schemaParser' threw exception; nested exception is org.antlr.v4.runtime.misc.ParseCancellationException
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	... 63 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schemaParser' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLJavaToolsAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.coxautodev.graphql.tools.SchemaParser]: Factory method 'schemaParser' threw exception; nested exception is org.antlr.v4.runtime.misc.ParseCancellationException
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	... 77 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.coxautodev.graphql.tools.SchemaParser]: Factory method 'schemaParser' threw exception; nested exception is org.antlr.v4.runtime.misc.ParseCancellationException
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	... 90 common frames omitted
Caused by: org.antlr.v4.runtime.misc.ParseCancellationException: null
	at org.antlr.v4.runtime.BailErrorStrategy.recoverInline(BailErrorStrategy.java:90) ~[antlr4-runtime-4.5.1.jar:4.5.1]
	at graphql.parser.antlr.GraphqlParser.name(GraphqlParser.java:1361) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.antlr.GraphqlParser.fieldDefinition(GraphqlParser.java:2959) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.antlr.GraphqlParser.objectTypeDefinition(GraphqlParser.java:2834) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.antlr.GraphqlParser.typeDefinition(GraphqlParser.java:2654) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.antlr.GraphqlParser.typeSystemDefinition(GraphqlParser.java:2437) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.antlr.GraphqlParser.definition(GraphqlParser.java:250) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.antlr.GraphqlParser.document(GraphqlParser.java:166) ~[graphql-java-3.0.0.jar:na]
	at graphql.parser.Parser.parseDocument(Parser.java:29) ~[graphql-java-3.0.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:101) ~[graphql-java-tools-3.1.0.jar:na]
	at com.oembedler.moon.graphql.boot.GraphQLJavaToolsAutoConfiguration.schemaParser(GraphQLJavaToolsAutoConfiguration.java:63) ~[graphql-spring-boot-autoconfigure-3.4.0.jar:na]
	at com.oembedler.moon.graphql.boot.GraphQLJavaToolsAutoConfiguration$$EnhancerBySpringCGLIB$$a1eebc7f.CGLIB$schemaParser$0(<generated>) ~[graphql-spring-boot-autoconfigure-3.4.0.jar:na]
	at com.oembedler.moon.graphql.boot.GraphQLJavaToolsAutoConfiguration$$EnhancerBySpringCGLIB$$a1eebc7f$$FastClassBySpringCGLIB$$86389778.invoke(<generated>) ~[graphql-spring-boot-autoconfigure-3.4.0.jar:na]
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at com.oembedler.moon.graphql.boot.GraphQLJavaToolsAutoConfiguration$$EnhancerBySpringCGLIB$$a1eebc7f.schemaParser(<generated>) ~[graphql-spring-boot-autoconfigure-3.4.0.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	... 91 common frames omitted
Caused by: org.antlr.v4.runtime.InputMismatchException: null
	at org.antlr.v4.runtime.BailErrorStrategy.recoverInline(BailErrorStrategy.java:85) ~[antlr4-runtime-4.5.1.jar:4.5.1]
	... 111 common frames omitted

Field deprecation via schema using directive @deprecated

There doesn't seem to be a way to publish deprecated messages for Fields/Enums. There is an implementation of a @deprecated directive added to the graphql-js implementation found At this merge. Could we add this processing to the SchemaParser.kt class so we can deprecate via the schema?

I'm currently working on adding this and was wondering if there were any issues you might have with this? I noticed on the README.md for 3.0 that the @doc directive seems to have been removed. Is there a reason for this? Are directives being removed completely? If so, how are we going to be able to deprecate fields/enums in the schema?

Can't share class with input type

Trying to use the same class with a normal type and input type in the same schema results in an java.lang.IllegalArgumentException: value already present exception for the class in question.

import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import com.coxautodev.graphql.tools.SchemaParser;

public class Example implements GraphQLQueryResolver, GraphQLMutationResolver {
  public static void main(String... args) {
    SchemaParser.newParser()
        .schemaString(
            "type Value { s: String }" +
            "type ValueInput { s: String }" +
            "type Query { get: Value! }" +
            "type Mutation { set(value: ValueInput): String! }"
        )
    .resolvers(new Example())
    .build();
  }

  public Value get() { return new Value(); }

  public String set(Value value) { return value.getS(); }

  static class Value {
    private String s;
    public String getS() { return s; }
    public void setS(String s) { this.s = s; }
  }
}

Running this with graphql-java-tools 4.1.0 throws

Exception in thread "main" com.coxautodev.graphql.tools.SchemaClassScannerError: Error creating bimap of type => class
	at com.coxautodev.graphql.tools.SchemaClassScanner.validateAndCreateParser(SchemaClassScanner.kt:126)
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:96)
	at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:126)
	at Example.main(Example.java:15)
Caused by: java.lang.IllegalArgumentException: value already present: class Example$Value
	at com.google.common.collect.HashBiMap.put(HashBiMap.java:287)
	at com.google.common.collect.HashBiMap.put(HashBiMap.java:262)
	at com.coxautodev.graphql.tools.SchemaClassScanner.validateAndCreateParser(SchemaClassScanner.kt:123)
	... 3 more

Explicitly adding the name and class with dictionary results in a similar exception.

Use input types in unions

Following a discussion about how to use unions for input types I wrote the following schema.

union LocationInput = GeoLocationInput | AddressInput

input GeoLocationInput {
  lat: Float!
  lng: Float!
}

input AddressInput {
  street: String!
  number: String!
  postCode: String!
  place: String!
}

When processing my schema I get the following error:

com.coxautodev.graphql.tools.SchemaClassScannerError: TODO

	at com.coxautodev.graphql.tools.SchemaClassScanner.getAllObjectTypeMembersOfDiscoveredUnions(SchemaClassScanner.kt:170)
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:121)
	at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:118)
	at com.careibu.landing.graphql.SchemaTest.testSchema(SchemaTest.java:36)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:316)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:114)
	at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.lambda$invokeTestMethod$6(MethodTestDescriptor.java:171)
	at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
	at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.invokeTestMethod(MethodTestDescriptor.java:168)
	at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.execute(MethodTestDescriptor.java:115)
	at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.execute(MethodTestDescriptor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$1(HierarchicalTestExecutor.java:81)
	at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:76)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$1(HierarchicalTestExecutor.java:91)
	at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:76)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$1(HierarchicalTestExecutor.java:91)
	at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:76)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:51)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:87)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:62)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Looking at the code it seems to me like the method com.coxautodev.graphql.tools.SchemaClassScanner.getAllObjectTypeMembersOfDiscoveredUnions(SchemaClassScanner.kt:170) expects all union subtypes to be GraphQL type and not input.

I've debugged to make sure the definition it's trying to lookup is GeoLocationInput.

Am I doing something wrong in my schema definition or is this a limitation of graphql-java-tools?

Provide means for resolvers to define their type name

Please consider adding means for resolvers to say what GraphQL type they resolve. It could be an annotation, or an overrideable method that defaults to class name. Either of these could be implement as backwards-compatible, non-breaking change.

Why?

I'm using graphql-java-tools with Spring. My root resolver happens to be a Spring bean that is using some AOP (e.g. for authorization). Spring does that by creating a CGLIB proxy, which is just a subclass. As a result, I get an instance of Mutation$$EnhancerBySpringCGLIB$$2a4bb444 (subclass of Mutation). It blows up since the schema parser cannot find resolver for "Mutation".

I know I can configure schema parser using dictionary, but it's really tedious as I don't know the class type beforehand. It needs something like:

for (GraphQLResolver resolver : resolvers) {
    String name = resolver.getClass().getSimpleName();
    if (name.contains("CGLIB")) {
        name = resolver.getClass().getSuperclass().getSimpleName();
    }
    parser.dictionary(name, resolver.getClass());
}

This is really messy and tedious, compared to:

@Component
@GraphQLType("Mutation")
public class Mutation {
    // ...
}

or:

@Component
public class Mutation {
    // ...

    @Override
    public String getGraphQLType() {
        return "Mutation";
    }
}

SchemaClassScannerError when using float and java.lang.Float

I'm getting a runtime error with 3.0.1 because my data classes are using a mixture of java.lang.Float and float.

com.coxautodev.graphql.tools.SchemaClassScannerError: Two different classes used for type Float:

Is there a way of overriding this behaviour. As I'm not able to change the classes. I've worked around it by creating wrappers in the resolver class to make everything consistent. But that seems like quite a bit of redundant effort.

Thanks
Mark

Support property lookup by field (not just methods)

I'd like to be able to use immutable data types, implemented as classes with public final fields like this:

public class Foo {
    public final String bar;

    public Foo(String bar) {
        this.bar = bar;
    }
}

However, right now graphql-java-tools seems to require bar to be a method or a getter (like getBar()).

I can work this around by adding a getter, but it's really noisy and messy:

public class Foo {
    public final String bar;

    public Foo(String bar) {
        this.bar = bar;
    }

    public String getBar() {
        return bar;
    }
}

Splitting root query and mutation across many classes

Sorry if this is already possible, but would it be an option to have the root query and mutation objects split across many classes?

As best I can tell at present, these are only one single class, so if you have a large number of query fields - as a reasonable size API will - then they all end up in the same class. Worse though, this one class has many different concerns to worry about.

For example, the Query class on a blog might have to support: Users, Posts, Comments, and several different query methods for each of these.

Override Internal Server Errors

Hello, guys!

First of all thank you for this awesome library.

But I have a question, some of my methods in GraphQLQueryResolver throws exceptions, like AccessDeniedException, UnauthorizedException, ...

Result for /graphql will be something like:

{
  "data": {
    "roles": null
  },
  "errors": [
    {
      "message": "Internal Server Error(s) while executing query"
    }
  ]
}

How can I override this behaviour for some of my exceptions and do custom error response?

Something like:

  "errors": [
    {
      "errorCode": "ACCESS_DENIED",
      "message": "You don't have permission to access roles"
    }
  ]

Usage of reflection reduces usefulness with Spring

If the lookup of Query, Mutation were not by class.getSimpleName() and instead by either annotation or interface/parent type, it would allow the Query class etc to be enhanced by Spring for validation, security, etc

Unfortunately, any attempt to do this now will fail as the proxy class generated by Spring etc will have a different name...

GraphQLSevlet issue

Hi Andrew,
The readonly properties of the GraphQLServlet is causing errors for me in your example. Do you have a way around this? thanks

Here

@PostConstruct
    void postConstruct() {
        this.readOnlySchema = graphQLSchema
        this.schema = graphQLSchema
    }

Caused by: groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: readOnlySchema for class: com.hbo.example.servlet.GraphQLController

Input Objects GraphQLObjectType cannot be cast to GraphQLInputType

I'm following the example listed here:
https://github.com/graphql-java/graphql-java-tools#input-objects

However, when I try to launch the app, I get the following error:

graphql.schema.GraphQLObjectType cannot be cast to graphql.schema.GraphQLInputType

This is basically what I've done:

class Query implements GraphQLQueryResolver {
    public int add(AdditionInput input) {
        return input.getFirst() + input.getSecond();
    }
}

class AdditionInput {
    private int first;
    private int second;
    
    // getFirst()
    // setFirst()
    // getSecond()
    // setSecond()
}

Am I missing something? Do I need to implement some interface on AdditionInput? Or is this a bug?

Support for mismatched class and type names via annotations

I'm currently writing an app using this, and I'm having all of my GraphQL classes with slightly awkward names. For example, I already have an internal class called User, which stores rich types (e.g. the ID is a UserId, the Last Modified date is an Instant). As such, I've got the GraphQL representation of this called UserModel, which means that there are no typename clashes and things work cleaner.

Unfortunately this means that in my schema I've got UserModel as the name, instead of just User.

I know there is Dictionary support for renaming classes, but it would be useful if I could just annotate the class and have it work automatically.

For example, if I could define my user class as:

@GraphQLType("User")
data class UserModel(
        val id: String,
        val version: String,
        val updated: String,
        val name: String,
        val email: String?,
)

then I can refer to it as "User" throughout the schema, whilst the actual code has a different name and I never have to worry about the dictionary for these types.

Exception with Scalar Date

We are using OffsetDateTime field on our types and Graphql OffsetDateTime Scalar for mappring.

public class GraphQLDateType extends GraphQLScalarType {

  public GraphQLDateType() {

    super("Date", "Date", new Coercing<OffsetDateTime, String>() {

      DateTimeFormatter fmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME;

      @Override
      public String serialize(Object input) {
        if (input instanceof OffsetDateTime) {
          return fmt.format((OffsetDateTime) input);
        } else {
          return null;
        }
      }

      @Override
      public OffsetDateTime parseValue(Object input) {
        if (input instanceof String) {
          return OffsetDateTime.from(fmt.parse((String) input));
        }
        return null;
      }

      @Override
      public OffsetDateTime parseLiteral(Object input) {
        if (input instanceof StringValue) {
          return OffsetDateTime.from(fmt.parse(((StringValue) input).getValue()));
        }
        return null;
      }
    });
  }
}

Queries are working fine.
Mutation do not work because Jackson (used by GraphQL Tools) cannot convert those OffsetDateTime fields.

GraphQL Tools uses its own instance of ObjectMapper (ResolverDataFetcher.kt). So we cannot load "JavaTimeModule()" on it to support OffsetDateTime.
(Jackson JSR310 dependency is loaded on our pom.xml but the module JavaTimeModule need to be registered to this instance of ObjectMapper)

It would be nice to export ObjectMapper in order to register Jackson data binding module.

Provide an example for Union types

Hello,

I'm having a bit of trouble implementing a union type with this library. Could you provide an example in the readme ?

Here is the schema I'm trying to implement, but I don't know which classes to provide or if I have to do something in te builder.

union CodePointValue = Int|String

type Query {
    codepoint(value: CodepointValue!): Codepoint
}

type Codepoint {
    value: Int!
    name: String!
}

And the config :

SchemaParser.newParser()
                .file("schema.graphqls")
                .dictionary(Codepoint.class)
                .resolvers(resolvers)
                .build()
                .makeExecutableSchema()
        ;
    }

Thanks in advance

Complex input types not mapped correctly

If I have an input type that refers to another input type, the inner type doesn't get mapped correctly.
Example:

input AuthData {
    email: Email!
    password: String!
}

input Email {
    email: String
}

And the corresponding POJO:

public class AuthData {

    private Email email;
    private String password;

   //gettes & setters for both fields
}

Email is just a simple mutable POJO as well.

Trying to map this results in strange logs and an error:

WARN com.coxautodev.graphql.tools.SchemaClassScanner - Schema type was defined but can never be accessed, and can be safely deleted: Email
[WARNING] unavailable
graphql.GraphQLException: type Email not found in schema

It first claims Email is unused, then it breaks because it's not found :/

I created a minimal project that demonstrates this here: https://github.com/kaqqao/graphql-java-tools-issue

I tried adding Email explicitly via dictionary but nothing changed. Also tried creating an AuthDataResolver#email method, but still nothing. I can't figure out if I'm doing something wrong or if this is a bug. The documentation on mapping inputs doesn't really exist and the example project doesn't have complex inputs...

Default argument values aren't correctly passed to the resolver method

I have the following schema

schema { query: Query }
type Query { returnArg(arg: Boolean = false): Boolean! }

and the query resolver has a method

fun returnArg(arg: Boolean) = arg

When I run a query with an explicit value { returnArg(arg: false) }, it works fine.

When I run just { returnArg }, it will pass a graphql.language.BooleanValue instance instead of Boolean to the resolver method, and I will get an error in the results caused by a ClassCastException.

When using variables (e.g. query($arg: Boolean = false) { returnArg(arg: $arg) }), it works fine even with the default.

Issue while implementing an interface to another interface in the schema.graphqls

I am trying to implement an interface to another interface as shown below.

interface SecondInterface {
	secondInterfaceValue : String
}

interface ThirdInterface implements SecondInterface {
	thirdInterfaceValue : String
}

And having the type implementing the ThirdInterface as below.

type ThirdImpl implements ThirdInterface {
	thirdInterfaceValue : String
	secondInterfaceValue : String
}

So with the above schema, if I run, I am facing the "Invalid Schema" exception.

Help w/ simple POJO

I've got a simple Address POJO, just a few String attributes and an id.

SchemaParser.newParser().dictionary(Address.class).build().makeExecutableSchema()

I get this exception:

org.antlr.v4.runtime.misc.ParseCancellationException
at org.antlr.v4.runtime.BailErrorStrategy.recover(BailErrorStrategy.java:75)
at graphql.parser.antlr.GraphqlParser.definition(GraphqlParser.java:260)
at graphql.parser.antlr.GraphqlParser.document(GraphqlParser.java:166)
at graphql.parser.Parser.parseDocument(Parser.java:29)
at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:101)
at com.test.graphql.GraphQLTest.test_SchemaParser(GraphQLTest.java:49)
...
Caused by: org.antlr.v4.runtime.NoViableAltException
at graphql.parser.antlr.GraphqlParser.definition(GraphqlParser.java:254)

What am I missing?

interfaces not working

When I try to to create a type implementing another interface I get this error. I added the schema used.

Jun 13, 2017 12:40:30 PM definitions
INFO: 
scalar DateTime

interface Node {
    id: Int!
    createdAt: DateTime!
    updatedAt: DateTime!
}

type Offer implements Node {
    id: Int!
    createdAt: DateTime!
    updatedAt: DateTime!

    name: String!
}

type Query {
    allOffers: [Offer]!
}

[vert.x-eventloop-thread-0] WARN com.coxautodev.graphql.tools.SchemaClassScanner - Schema type was defined but can never be accessed, and can be safely deleted: Node
Jun 13, 2017 12:40:30 PM io.vertx.ext.web.impl.RoutingContextImplBase
SEVERE: Unexpected exception in route
com.coxautodev.graphql.tools.SchemaError: Expected interface type with name 'Node' but found none!

Less strict verification of list types

I'm using the library with Spring and CGLIB-based proxies.

I have a mutation class that looks like this:

@Component
public class Mutation {
    public String changeIt(List<Foo> input) {
        // ...
    }
}

It works just fine, until I add something that wraps it in a CGLIB proxy (like @PreAuthorize on the mutation method). Then it blows up with:

Caused by: com.coxautodev.graphql.tools.SchemaClassScannerError: Unable to match type definition (NonNullType{type=ListType{type=TypeName{name='Foo'}}}) with java type (interface java.util.List): Java class is not a List: interface java.util.List
	at com.coxautodev.graphql.tools.TypeClassMatcher.error(TypeClassMatcher.kt:23) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.TypeClassMatcher.match(TypeClassMatcher.kt:60) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.TypeClassMatcher.match$default(TypeClassMatcher.kt:27) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.TypeClassMatcher.match(TypeClassMatcher.kt:53) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.TypeClassMatcher.match(TypeClassMatcher.kt:25) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.matchTypeToClass(SchemaClassScanner.kt:222) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.matchTypeToClass$default(SchemaClassScanner.kt:222) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.handleFieldMethod(SchemaClassScanner.kt:186) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanObjectForDictionaryItems(SchemaClassScanner.kt:175) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:93) ~[graphql-java-tools-3.1.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:107) ~[graphql-java-tools-3.1.0.jar:na]

The thing is, without the proxy the method argument obtained with reflection is parameterized List<Foo>. However, the proxy changes it to a plain List.


Does the schema actually need such strict verification?

One easy-ish way to solve it could be adding support for arrays. This should not lose type information:

public String changeIt(Foo[] input)

"Two different classes used for type" for scalar type

I have a GraphQLScalarType that serializes several different classes. With graphql-java-tools 2.2.0 I didn't have any issues, but after updating to 3.1.2 I get an error about using multiple classes for the scalar type.

scalar Scalar

type Type {
  a: Scalar
  b: Scalar
}
public class Type {
  public Object a() {
    return "a";
  }

  public String b() {
    return "b";
  }
}

I get this error:

com.coxautodev.graphql.tools.SchemaClassScannerError: Two different classes used for type Scalar:
- class java.lang.Object:
|   return type of method public java.lang.Object com.example.GraphQLToolsErrorExample$Type.a()

- null:
|   return type of method public java.lang.String com.example.GraphQLToolsErrorExample$Type.b()

(I filed #30 for the null in the error message)

I'm not sure if it is a bug, or if there's a way to tell graphql-java-tools that Scalar can be any subclass of Object.

Full Example

package com.example;

import com.coxautodev.graphql.tools.GraphQLRootResolver;
import com.coxautodev.graphql.tools.SchemaParser;

import graphql.schema.Coercing;
import graphql.schema.GraphQLScalarType;
import graphql.schema.GraphQLSchema;

public class GraphQLToolsErrorExample {
  public static class Type {
    public Object a() {
      return "a";
    }

    public String b() {
      return "b";
    }
  }

  public static class Query implements GraphQLRootResolver {
    public Type type() {
      return new Type();
    }
  }

  public static void main(String... args) {
    GraphQLSchema s = SchemaParser.newParser()
        .schemaString(
            "scalar Scalar type Type { a: Scalar b: Scalar} type Query { type: Type }")
        .resolvers(new Query())
        .scalars(new GraphQLScalarType("Scalar", "not a very interesting scalar", new Coercing() {
          public Object serialize(Object input) {
            return true;
          }

          public Object parseValue(Object input) {
            throw new UnsupportedOperationException();
          }

          public Object parseLiteral(Object input) {
            return true;
          }
        }))
        .build()
        .makeExecutableSchema();
  }
}

Better Kolin support

Do you have any plans to add a better support to Kotlin? I'd love to help if necessary. It's a bit annoying having to rely on converting some data to java like from KClass to Class.

Restore support for generics in Inputs & Types

requireRawClass() function added in bc9160d removes the ability to use generics to capture whether a field was posted or not when binding requests.

Example

class OptionalInput<T> {

    private boolean _set = false
    private T value

    void set(T value) {
        this._set = true
        this.value = value
    }

    T get() {
        return this.value
    }

    boolean isSet() {
        return this._set
    }
}
class SomeInput {
    final OptionalInput<String> name = new OptionalInput<String>()

    // The below setter are required for binding from the mutation request.

    void setName(String name) {
        this.name.set(name)
    }
}

class Mutation {
    Object updateName(SomeInput someInput)  {

        if (someInput.name.isSet()) {
            String name = someInput.name.get()
            // Do something as the data was posted
        } else {
            // Do nothing as not posted.  Otherwise Java String would be null and we would erroneously clear a value
        }
    }
}

Schema type was defined but can never be accessed

Hello, fellows!

I'm trying to use graphql with multiple schemas files (*.graphqls) and with Spring Boot.
But all my tries are resulting in this errors logged on console:

Schema type was defined but can never be accessed, and can be safely deleted: StarWarsResolver
Resolver was provided but no methods on it were used in data fetchers, and can be safely deleted: org.example.test.resolvers.StarWarsResolver@3f93e4a8

This errors occurs only the StarWarsResolver class and his types (Character, Human, etc).
The following code is below:

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.4.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

jar {
    baseName = 'gs-rest-service'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
	compile 'com.graphql-java:graphql-java-tools:3.1.0'
	compile 'com.graphql-java:graphql-spring-boot-starter:3.4.1'
	
    compile("org.springframework.boot:spring-boot-starter-web")
	compile("org.springframework.boot:spring-boot-starter-undertow")
    
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

test.graphqls

type Query {
  test(id: String!): Test
}

type Test {
  id: String!,
  name: String!,
  bla: String,
}

Query

@Component
public class Query implements GraphQLQueryResolver {

	@Autowired
	private TestRepository testRepository;

	public Test test(String id) {
		return testRepository.getTests().get(id);
	}
}

TestRepository

@Component
public class TestRepository {

	private Map<String, Test> tests;

	@Autowired
	public TestRepository() {
		Test test = new Test("1000", "Test", null);

		this.tests = Collections.unmodifiableMap(Stream.of(test).collect(Collectors.toMap(Test::getId, Function.identity())));
	}

	public Map<String, Test> getTests() {
		return tests;
	}
}

Test

public class Test {

	private String id;
	private String name;
	private String bla;

	public Test(String id, String name, String bla) {
		this.id = id;
		this.name = name;
		this.bla = bla;
	}

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public String getBla() {
		return bla;
	}
}

So far so good... But when I put the next graphqls file, the next resolver, type and repository, the errors occurs.
The following code is the same as your example of Star Wars Api.

starwars.graphqls

type StarWarsResolver {
    hero(episode: Episode): Character @doc(d: "If episode omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode")
    human(id: String!): Human @doc(d: "Find human by id")
    droid(id: String!): Droid @doc(d: "Find droid by id")
    character(id: String!): Character @doc(d: "Find character by id")
}

enum Episode @doc(d: "One of the films in the Star Wars Trilogy") {
    NEWHOPE @doc(d: "Released in 1977"),
    EMPIRE @doc(d: "Released in 1980"),
    JEDI @doc(d: "Released in 1983")
}

interface Character @doc(d: "A character in the Star Wars Trilogy") {
    id: String! @doc(d: "The id of the character"),
    name: String @doc(d: "The name of the character"),
    friends: [Character] @doc(d: "The friends of the character, or an empty list if they have none"),
    appearsIn: [Episode] @doc(d: "Which movies they appear in"),
}

type Human implements Character @doc(d: "A humanoid creature in the Star Wars universe") {
    id: String! @doc(d: "The id of the human"),
    name: String @doc(d: "The name of the human"),
    friends: [Character] @doc(d: "The friends of the human, or an empty list if they have none"),
    appearsIn: [Episode] @doc(d: "Which movies they appear in"),
    homePlanet: String @doc(d: "The home planet of the human, or null if unknown"),
}

type Droid implements Character @doc(d: "A mechanical creature in the Star Wars universe") {
    id: String! @doc(d: "The id of the droid"),
    name: String @doc(d: "The name of the droid"),
    friends: [Character] @doc(d: "The friends of the droid, or an empty list if they have none"),
    appearsIn: [Episode] @doc(d: "Which movies they appear in"),
    primaryFunction: String @doc(d: "The primary function of the droid"),
}

StarWarsResolver

@Component
public class StarWarsResolver implements GraphQLQueryResolver {

	@Autowired
	private CharacterRepository characterRepository;

	public Character hero(Episode episode) {
		return episode != null ? characterRepository.getHeroes().get(episode) : characterRepository.getCharacters().get("1000");
	}

	public Human human(String id) {
		return (Human) characterRepository.getCharacters().values().stream().filter(character -> character instanceof Human && character.getId().equals(id)).findFirst().orElseGet(null);
	}

	public Droid droid(String id) {
		return (Droid) characterRepository.getCharacters().values().stream().filter(character -> character instanceof Droid && character.getId().equals(id)).findFirst().orElseGet(null);
	}

	public Character character(String id) {
		return characterRepository.getCharacters().get(id);
	}

The Types and Repository classes are the same as your example...

I checked that all graphqls files are getting to Schema builder, but on running this erros are logged.
I already have tried a bunch ways for resolve the problem but I'm stuck.
Can you help me?

Nested input types are not working

I have such schema root.graphqls:

input AuthorInput {
    id: Int
    name: String!
}

input BookInput {
    id: Int!
    name: String
    authorInput: AuthorInput
}

type BookMutation {
    createBook(bookInput: BookInput!): Book
}

//other types

and appropriate java model classes. When I run

SchemaParser schemaParser = SchemaParser.newParser()
                .file("my/model/root.graphqls")
                .resolvers(new QueryResolver(bookRepository), new MutationResolver(bookRepository))
                .build();

GraphQLSchema graphQLSchema = schemaParser.makeExecutableSchema();

I get [main] WARN c.c.g.t.SchemaClassScanner - Schema type was defined but can never be accessed, and can be safely deleted: AuthorInput

and

Exception in thread "main" graphql.GraphQLException: type AuthorInput not found in schema
	at graphql.schema.SchemaUtil.resolveTypeReference(SchemaUtil.java:217)
	at graphql.schema.GraphQLInputObjectField.replaceTypeReferences(GraphQLInputObjectField.java:44)
	at graphql.schema.SchemaUtil.resolveTypeReferencesForInputFieldsContainer(SchemaUtil.java:209)
	at graphql.schema.SchemaUtil.replaceTypeReferences(SchemaUtil.java:187)
	at graphql.schema.GraphQLSchema$Builder.build(GraphQLSchema.java:131)
	at com.coxautodev.graphql.tools.SchemaObjects.toSchema(SchemaObjects.kt:18)
	at com.coxautodev.graphql.tools.SchemaParser.makeExecutableSchema(SchemaParser.kt:83)
	at my.graphql.Main.main(Main.java:28)

According to spec:

Input types can't have fields that are other objects, only basic scalar types, list types, and other input types.

Do I use this in some wrong way?

Dynamic models without POJOs

My java code doesn't have POJOs for most of the models because they are user-defined and stored in the database (i.e. CMS). I'm struggling to return the results since GraphQLResolver requires a POJO. Is there a way of returning Maps?

schema.json

Is here some module/function to generate schema.json from GraphQLSchema ?

kotlinx coroutines CompletableFuture

Writing a resolver using kotlinx-coroutines-jdk8

fun allUsers() = future {
  arrayListOf()
}

Throws an error, CompletableFutureCoroutine cannot be cast to java.lang.Iterable

It does the same when using CompletableFuture without kotlinx

Improved error messages

Currently when the resolvers are not wired up correctly the errors you get back tell you exactly what's wrong, and fixing it is easy.

However, if one of the graphqls files is invalid, you get a very cryptic antlr error that tells you nothing. I've had to resort to the debugger to find the line number in my file that is wrong and fix it that way.

Recursive input type breaks if wrapped in a list

The following scenario seems to break:

type Query {
    allLinks(filter: LinkFilter): [Link]
}

input LinkFilter {
    OR: [LinkFilter!]
    description_contains: String
    url_contains: String
}

And the LinkFilter POJO:

public class LinkFilter {

    private List<LinkFilter> OR;
    private String description_contains;
    private String url_contains;

    //getters & setters
}

The exceptions is:

com.coxautodev.graphql.tools.SchemaClassScannerError: Two different classes used for type LinkFilter:
- class com.something.LinkFilter:
| parameter 0 of method public java.util.List com.something.Query.allLinks(com.something.LinkFilter)
- interface java.util.List:
| input object InputValueDefinition{name='OR', type=ListType{type=NonNullType{type=TypeName{name='LinkFilter'}}}, defaultValue=null, directives=[]}

If I unwrap the OR field to just a LinkFilter, everything is fine.

List of Object as Input in Mutation

Hi,

i have a question about parameter passing in a mutation.

My schema looks something like this:

input KeyValuePairInput {
    key: String!
    value: String!
    valueType: ValueTypeEnum
}
enum ValueTypeEnum {
    Int
    Float
    String
    Boolean
}

with a Mutation and a method in it:

someFunction(
        name: String!
        key: String
        variables: [KeyValuePairInput]
    ): SomeReturn

The corresponding Resolver for my Mutation has a public method

public class Mutation implements GraphQLRootResolver {
..
    public SomeReturn someFunction(String name, String key, ArrayList<KeyValuePairInput> variables) {}
}

Now when a call the mutation, the Java method gets called, but the type of the variables is ArrayList. Am i missing something here? I expected it to be ArrayList.

Sorry if the question is stupid, but i can't find a solution to this problem.

Interfaces - having multiple interfaces in schema generates errors on startup

Issue
If schema has multiple interfaces, then the app fails to start.

Reproduction
Given the following example schema and its corresponding java classes:

type Query {
    query1(resource: NamedResourceImpl): [Long!]
    query2(resource: VersionedResourceImpl): [Long!]
}


interface NamedResource {
    name: String!
}

interface VersionedResource {
    version: Int!
}

type NamedResourceImpl implements NamedResource {
    name: String!
}

type VersionedResourceImpl implements VersionedResource {
    version: Int!
}

When the application is starting,

The following exception is being thrown:

Caused by: com.coxautodev.graphql.tools.SchemaClassScannerError: Error creating bimap of type => class
	at com.coxautodev.graphql.tools.SchemaClassScanner.validateAndCreateParser(SchemaClassScanner.kt:141) ~[graphql-java-tools-3.2.1.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:124) ~[graphql-java-tools-3.2.1.jar:na]

Caused by: java.lang.IllegalArgumentException: value already present: null
	at com.google.common.collect.HashBiMap.put(HashBiMap.java:287) ~[guava-21.0.jar:na]
	at com.google.common.collect.HashBiMap.put(HashBiMap.java:262) ~[guava-21.0.jar:na]
	at com.coxautodev.graphql.tools.SchemaClassScanner.validateAndCreateParser(SchemaClassScanner.kt:138) ~[graphql-java-tools-3.2.1.jar:na]
	... 81 common frames omitted

Error Handling

Hi guys, good work.

We would like to base our project camunda-graphql on your graphql-java-tools.
My question:
When using graphq-java-tools what is the best way or level to implement GraphQL Error Handling?
I.e. error/exception handling when something goes wrong in the resolvers, like here for example.
Currently the error gets reported on the server console, but the response in GraphiQL look like this:
image

How can I put the exception-message ("no processes deployed with key 'x': processDefinition is null") from the API-call into the GraphQL response?

Update: it looks like GraphQLServlet is responsible for adding the error(s) to the response. Although there are errors (here: ExceptionWhileDataFetching) from the result of new GraphQL (which is OK) they are not getting inserted into the JSON-response.

Feature: Schema to Data Class/Resolver Nullability Rules Matches Kotlin Classes

It would be a nice feature to have the SchemaParser have the ability to validate that a given type matches the nullability rules in a Kotlin defined data class or resolver.

So, when we have something like this in GraphQL:

type Something {
  attributeOne: String!
  attributeTwo: String
}

The SchemaParser would fail, and describe the error, if we attempted to define/register a data class for that type if it were defined as the following (note the nullability rules have been flipped in the Kotlin definition):

data class Something(attributeOne: String?, attributeTwo: String)

Without this option, the only way to find out there is a mismatch between schema and implementation is at runtime. The wonderful thing about Kotlin is that we have that information natively without relying on developers to add annotations and such in Java.

We could implement this as an opt-in option in the builder. This would be very easy for Kotlin. There can also be an opt-in for Java classes if they use the @nullable and @NotNull annotations from Jetbrains.

Again, I'm willing to implement this. Probably more as a strategy and not inlining it with the current codebase. I'd do the Kotlin one first as that satisfies my immediate needs.

Schema building fails if interfaces are not directly referred to

I've received a complaint from someone trying to add interfaces to the Link type from HowToGraphQL. The example code is here.

Link (an object type) has 2 interfaces: LinkInterface and SecondInterface. None of the interfaces are directly used in the schema i.e. all queries/mutations use Link directly.

What happens is that an error is thrown in SchemaClassScanner.kt:138, because typeClass for both interfaces is null, so null effectively becomes a duplicate key in the map ultimately causing an exception.

From my own experiments, if the interfaces are used directly e.g. I change the allLinks query to return [LinkInterface] instead of [Link], everything is fine. I tried registering the interface classes directly via SchemaParser#dictionary but it doesn't make a difference.

IncompatibleClassChangeError on DataFetchingEnvironment when graphql-jav 2.4.0 is used

Hi,

I'm trying to use the graphql-spring boot starter with this library, but there is an incompatibility.

The Spring Boot starter includes the latest version of graphql-java : the 2.4.0 where among other things, the DataFetchingEnvironment became an interface instead of a class.

When executing a query, I get the following error :

java.lang.IncompatibleClassChangeError: Found interface graphql.schema.DataFetchingEnvironment, but class was expected
	at com.coxautodev.graphql.tools.ResolverDataFetcher$Companion$create$$inlined$forEachIndexed$lambda$1.invoke(ResolverDataFetcher.kt:49) ~[graphql-java-tools-2.1.3.jar:na]
	at com.coxautodev.graphql.tools.ResolverDataFetcher$Companion$create$$inlined$forEachIndexed$lambda$1.invoke(ResolverDataFetcher.kt:15) ~[graphql-java-tools-2.1.3.jar:na]
	at com.coxautodev.graphql.tools.ResolverDataFetcher.get(ResolverDataFetcher.kt:95) ~[graphql-java-tools-2.1.3.jar:na]
	at graphql.execution.ExecutionStrategy.resolveField(ExecutionStrategy.java:66) ~[graphql-java-2.4.0.jar:na]
	at graphql.execution.SimpleExecutionStrategy.execute(SimpleExecutionStrategy.java:18) ~[graphql-java-2.4.0.jar:na]
	at graphql.execution.Execution.executeOperation(Execution.java:85) ~[graphql-java-2.4.0.jar:na]
	at graphql.execution.Execution.execute(Execution.java:44) ~[graphql-java-2.4.0.jar:na]
	at graphql.GraphQL.execute(GraphQL.java:201) ~[graphql-java-2.4.0.jar:na]
	at graphql.servlet.GraphQLServlet.query(GraphQLServlet.java:271) [graphql-java-servlet-2.1.1.jar:na]
	at graphql.servlet.GraphQLServlet.lambda$new$1(GraphQLServlet.java:185) [graphql-java-servlet-2.1.1.jar:na]
	at graphql.servlet.GraphQLServlet.doRequest(GraphQLServlet.java:228) [graphql-java-servlet-2.1.1.jar:na]
	at graphql.servlet.GraphQLServlet.doPost(GraphQLServlet.java:246) [graphql-java-servlet-2.1.1.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) [spring-boot-actuator-2.0.0.BUILD-SNAPSHOT.jar:2.0.0.BUILD-SNAPSHOT]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) [spring-boot-actuator-2.0.0.BUILD-SNAPSHOT.jar:2.0.0.BUILD-SNAPSHOT]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.0.RC1.jar:5.0.0.RC1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.14.jar:8.5.14]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121]

This problem could probably be solved by bumping graphql-java to version 2.4.0 and fixing the build.

I'd open a pull request, but unfortunately I don't know kotlin :(

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.