我想为未来的项目测试 GraphQL。该项目将使用 Spring Boot、Spring Security 和 GraphQL。因此,我使用 Spring Initializr 中的构建在 IntelliJ 中创建了一个新的 Spring Boot 应用程序。Spring Boot 版本当然是最新的(2.0.3.RELEASE) 现在我添加 GraphQL 和 GraphiQL 的依赖项。
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
为了测试这一点,我运行了应用程序,但没有/graphql
端点。在这种情况下,我将其配置为application.properties
没有问题:
# GraphQL
graphql.servlet.mapping=/graphql
graphql.servlet.enabled=true
graphql.servlet.corsEnabled=true
# GraphiQL
graphiql.mapping=/graphiql
graphiql.endpoint=/graphql
graphiql.enabled=true
graphiql.cdn.enabled=true
graphiql.cdn.version=0.11.11
再次测试后,端点就在那里,所以现在我可以编写模式、解析器等。这是我实现的:
架构:
schema {
query: Query
mutation: Mutation
}
type Greeting {
id: ID!
message: String!
}
type Query {
greetingsAll: [Greeting]
}
type Mutation {
greeting(message: String!): Greeting
}
模型:
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
@ToString
@Entity
public class Greeting {
@Id
@GeneratedValue
private Long id;
private String message;
}
存储库
@Repository
public interface GreetingRepository extends JpaRepository<Greeting, Long> {
}
查询解析器
@Component
public class QueryResolver implements GraphQLQueryResolver {
@Autowired
private GreetingRepository greetingRepository;
public Greeting greeting(Long id) {
return greetingRepository.getOne(id);
}
public Iterable<Greeting> getGreetingsAll() {
return greetingRepository.findAll();
}
}
突变解析器
@Component
public class MutationResolver implements GraphQLMutationResolver {
@Autowired
private GreetingRepository greetingRepository;
public Greeting newGreeting(String message) {
Greeting greeting = new Greeting();
greeting.setMessage(message);
return greetingRepository.save(greeting);
}
}
SpringBoot 的 Bean
@SpringBootApplication
public class GraphqlApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlApplication.class, args);
}
@Bean
ApplicationRunner init(GreetingRepository greetingRepository) {
return args -> {
Stream.of("Hallo", "Guten Tag", "Moin").forEach(greeting -> greetingRepository.save(Greeting.builder().message(greeting).build()));
greetingRepository.findAll().forEach(System.out::println);
};
}
@Bean
public QueryResolver query() {
return new QueryResolver();
}
@Bean
public MutationResolver mutation() {
return new MutationResolver();
}
}
在尝试再次测试应用程序以查看是否可以使用 GraphiQL 运行查询时,应用程序无法启动:
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at de.eno.prototyp.graphql.GraphqlApplication.main(GraphqlApplication.java:14) [classes/:na]
Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:126) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:86) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:413) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:174) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.0.3.RELEASE.jar:2.0.3.RELEASE]
... 8 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLServletRegistrationBean' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLServletRegistrationBean' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLServlet' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLServlet' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLSchemaProvider' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLSchemaProvider' parameter 0; nested exception is 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 com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:474) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1256)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLServlet' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLServlet' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLSchemaProvider' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLSchemaProvider' parameter 0; nested exception is 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 com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:474) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1256) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
... 24 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'graphQLSchemaProvider' defined in class path resource [com/oembedler/moon/graphql/boot/GraphQLWebAutoConfiguration.class]: Unsatisfied dependency expressed through method 'graphQLSchemaProvider' parameter 0; nested exception is 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 com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:474) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1256) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
... 38 common frames omitted
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 com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:474)
... 52 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 com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:590) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1256)
... 66 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 com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
... 79 common frames omitted
Caused by: com.coxautodev.graphql.tools.FieldResolverError: Found more than one matching resolver for field 'FieldDefinition{name='greetingsAll', type=ListType{type=TypeName{name='Greeting'}}, inputValueDefinitions=[], directives=[]}': [MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}, MethodFieldResolver{method=public java.lang.Iterable de.eno.prototyp.graphql.QueryResolver.getGreetingsAll()}]
at com.coxautodev.graphql.tools.FieldResolverScanner.findFieldResolver(FieldResolverScanner.kt:39) ~[graphql-java-tools-5.2.0.jar:na]
at com.coxautodev.graphql.tools.SchemaClassScanner.scanResolverInfoForPotentialMatches(SchemaClassScanner.kt:227) ~[graphql-java-tools-5.2.0.jar:na]
at com.coxautodev.graphql.tools.SchemaClassScanner.handleRootType(SchemaClassScanner.kt:122) ~[graphql-java-tools-5.2.0.jar:na]
at com.coxautodev.graphql.tools.SchemaClassScanner.scanForClasses(SchemaClassScanner.kt:80) ~[graphql-java-tools-5.2.0.jar:na]
at com.coxautodev.graphql.tools.SchemaParserBuilder.scan(SchemaParserBuilder.kt:150) ~[graphql-java-tools-5.2.0.jar:na]
at com.coxautodev.graphql.tools.SchemaParserBuilder.build(SchemaParserBuilder.kt:156) ~[graphql-java-tools-5.2.0.jar:na]
at com.oembedler.moon.graphql.boot.GraphQLJavaToolsAutoConfiguration.schemaParser(GraphQLJavaToolsAutoConfiguration.java:65) ~[graphql-spring-boot-autoconfigure-4.3.0.jar:na]
所以我不知道发生了什么,但我认为 GraphQL 无法将Query
类型映射到QueryResolver
. 但为什么?
检查互联网时,我读到 Spring Boot 版本是原因。所以我用 Spring Boot 1.5.8.RELEASE 对其进行了测试,没有结果。
但是,当使用 Spring boot 1.5.8 的旧 GraphQL 版本(4.3.0 和 5.2.0)时,它似乎工作正常。因此,我尝试将这些较旧的 GraphQL 版本与新的 Spring 引导版本一起使用,但随后出现另一个异常:
2018-07-13 14:45:57.666 INFO 12872 --- [io-8080-exec-10] graphql.servlet.GraphQLServlet : Bad POST request: parsing failed
java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
at org.apache.catalina.connector.Request.parseParts(Request.java:2826) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.connector.Request.getParts(Request.java:2793) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1084) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at graphql.servlet.GraphQLServlet.lambda$new$2(GraphQLServlet.java:129) ~[graphql-java-servlet-5.1.0.jar:na]
at graphql.servlet.GraphQLServlet.doRequest(GraphQLServlet.java:260) ~[graphql-java-servlet-5.1.0.jar:na]
at graphql.servlet.GraphQLServlet.doPost(GraphQLServlet.java:278) ~[graphql-java-servlet-5.1.0.jar:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
现在,由于这种不兼容,我真的搞砸了。我想使用所有库的新版本。有人有解决方案吗?