diff --git a/spring-graphql-docs/modules/ROOT/nav.adoc b/spring-graphql-docs/modules/ROOT/nav.adoc index ed3f3286..0d80b79f 100644 --- a/spring-graphql-docs/modules/ROOT/nav.adoc +++ b/spring-graphql-docs/modules/ROOT/nav.adoc @@ -12,4 +12,5 @@ * xref:graphiql.adoc[] * xref:testing.adoc[] * xref:boot-starter.adoc[] +* xref:standalone-setup.adoc[] * xref:samples.adoc[] diff --git a/spring-graphql-docs/modules/ROOT/pages/standalone-setup.adoc b/spring-graphql-docs/modules/ROOT/pages/standalone-setup.adoc new file mode 100644 index 00000000..5fa3feb5 --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/pages/standalone-setup.adoc @@ -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]. diff --git a/spring-graphql-docs/src/main/java/org/springframework/graphql/docs/standalonesetup/GraphQlConfiguration.java b/spring-graphql-docs/src/main/java/org/springframework/graphql/docs/standalonesetup/GraphQlConfiguration.java new file mode 100644 index 00000000..aee907a6 --- /dev/null +++ b/spring-graphql-docs/src/main/java/org/springframework/graphql/docs/standalonesetup/GraphQlConfiguration.java @@ -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 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(); + } +}