Skip to content

Commit

Permalink
Document minimum standalone setup for GraphQL support
Browse files Browse the repository at this point in the history
Most Spring for GraphQL applications use Spring Boot as a way to
auto-configure the required infrastructure for running GraphQL
applications.

This commit documents a minimal setup for Spring applications not
relying on Spring Boot. This assumes an existing infrastructure for a
Spring MVC application.

Closes gh-606
  • Loading branch information
bclozel committed Jul 12, 2024
1 parent 441b18d commit c1ed773
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions spring-graphql-docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
* xref:graphiql.adoc[]
* xref:testing.adoc[]
* xref:boot-starter.adoc[]
* xref:standalone-setup.adoc[]
* xref:samples.adoc[]
15 changes: 15 additions & 0 deletions spring-graphql-docs/modules/ROOT/pages/standalone-setup.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[[standalone-setup]]
= Standalone Setup

If your application is not using Spring Boot, you are responsible for setting up the relevant Spring for GraphQL components.
Assuming that your application is already configured for Spring MVC controllers, the minimum setup will require several beans.

include-code::GraphQlConfiguration[]
<1> The `AnnotatedControllerConfigurer` bean is responsible for detecting GraphQL `@Controller` handlers.
<2> The `ExecutionGraphQlService` processes GraphQL requests in a transport-agnostic fashion.
<3> The `GraphQlSource` builder is the main configuration point. Explore its API for more options.
<4> The `RouterFunction` exposes the GraphQL routes as {spring-framework-ref-docs}/web/webmvc-functional.html[functional endpoints].
<5> You can then expose various transports (WebSocket, SSE, HTTP) over different routes.

Spring for GraphQL offers many other options and integrations with Spring projects.
For more on this, you can xref:boot-starter.adoc[explore the Spring Boot auto-configurations].
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2020-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.graphql.docs.standalonesetup;

import java.util.List;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.graphql.data.method.annotation.support.AnnotatedControllerConfigurer;
import org.springframework.graphql.execution.ConnectionTypeDefinitionConfigurer;
import org.springframework.graphql.execution.DefaultBatchLoaderRegistry;
import org.springframework.graphql.execution.DefaultExecutionGraphQlService;
import org.springframework.graphql.execution.GraphQlSource;
import org.springframework.graphql.server.WebGraphQlHandler;
import org.springframework.graphql.server.webmvc.GraphQlHttpHandler;
import org.springframework.graphql.server.webmvc.GraphQlRequestPredicates;
import org.springframework.graphql.server.webmvc.GraphiQlHandler;
import org.springframework.web.servlet.function.RequestPredicate;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;

@Configuration(proxyBeanMethods = false)
public class GraphQlConfiguration {

@Bean // <1>
public AnnotatedControllerConfigurer controllerConfigurer() {
return new AnnotatedControllerConfigurer();
}

@Bean // <2>
public ExecutionGraphQlService executionGraphQlService(AnnotatedControllerConfigurer controllerConfigurer) {
GraphQlSource graphQlSource = GraphQlSource.schemaResourceBuilder() // <3>
.schemaResources(new ClassPathResource("graphql/schema.graphqls"))
.configureTypeDefinitions(new ConnectionTypeDefinitionConfigurer())
.configureRuntimeWiring(controllerConfigurer)
.exceptionResolvers(List.of(controllerConfigurer.getExceptionResolver()))
.build();
DefaultBatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();
DefaultExecutionGraphQlService service = new DefaultExecutionGraphQlService(graphQlSource);
service.addDataLoaderRegistrar(batchLoaderRegistry);
return service;
}


@Bean // <4>
public RouterFunction<ServerResponse> graphQlRouterFunction(ExecutionGraphQlService graphQlService) {
WebGraphQlHandler webGraphQlHandler = WebGraphQlHandler.builder(graphQlService).build();
GraphQlHttpHandler graphQlHttpHandler = new GraphQlHttpHandler(webGraphQlHandler);
RequestPredicate graphQlPredicate = GraphQlRequestPredicates.graphQlHttp("/graphql");
GraphiQlHandler graphiQlHandler = new GraphiQlHandler("/graphql", "");
return RouterFunctions.route() // <5>
.route(graphQlPredicate, graphQlHttpHandler::handleRequest)
.GET("/graphiql", graphiQlHandler::handleRequest)
.build();
}
}

0 comments on commit c1ed773

Please sign in to comment.