diff --git a/spring-graphql-docs/src/docs/asciidoc/boot-starter.adoc b/spring-graphql-docs/src/docs/asciidoc/boot-starter.adoc new file mode 100644 index 00000000..9d668d0c --- /dev/null +++ b/spring-graphql-docs/src/docs/asciidoc/boot-starter.adoc @@ -0,0 +1,423 @@ +[[boot-graphql]] += Boot Starter + +This projects builds on Boot 2.5.x, but it should be compatible with the latest Boot 2.4.x. + + + +[[boot-graphql-project]] +== Project Setup + +To create a project, go to https://start.spring.io and select starter(s) for the +GraphQL transports you want to use: + +[cols="1,1,1"] +|=== +| Starter | Transport | Implementation + +| `spring-boot-starter-web` +| HTTP +| Spring MVC + +| `spring-boot-starter-websocket` +| WebSocket +| WebSocket for Servlet apps + +| `spring-boot-starter-webflux` +| HTTP, WebSocket +| Spring WebFlux + +|=== + +In the generated project, add `graphql-spring-boot-starter` manually: + +[source,groovy,indent=0,subs="verbatim,quotes",role="primary"] +.Gradle +---- +dependencies { + // Spring GraphQL Boot starter + implementation 'org.springframework.experimental:graphql-spring-boot-starter:1.0.0-SNAPSHOT' + + // ... +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } // Spring milestones + maven { url 'https://repo.spring.io/snapshot' } // Spring snapshots +} +---- +[source,xml,indent=0,subs="verbatim,quotes",role="secondary"] +.Maven +---- + + + // Spring GraphQL Boot starter + + org.springframework.experimental + graphql-spring-boot-starter + 1.0.0-SNAPSHOT + + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + +---- + +[NOTE] +.Boot Starter Group Id +==== +The Boot starter will move from the Spring GraphQL repository to the Spring Boot +repository, after Spring Boot 2.6 is released. The group id for the starter will then +change from `org.springframework.experimental` to `org.springframework.boot` and will be +released in Spring Boot 2.7. +==== + + + +[[boot-graphql-schema]] +== Schema + +By default, GraphQL schema files are expected to be in `src/main/resources/graphql` and have +the extension ".graphqls", ".graphql", ".gql", or ".gqls". You can customize the +schema locations to check as follows: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +spring.graphql.schema.locations=classpath:graphql/ +---- + +The GraphQL schema can be viewed over HTTP at "/graphql/schema". This is not enabled by +default: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +spring.graphql.schema.printer.enabled=false +---- + + +[[boot-graphql-datafetcher]] +== `DataFetcher` Registration + +You can declare `RuntimeWiringCustomizer` beans in your Spring config and use those to +register data fetchers, type resolvers, and more with the GraphQL engine: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +@Component +public class PersonDataWiring implements RuntimeWiringCustomizer { + + private final PersonService service; + + public PersonDataWiring(PersonService service) { + this.service = service; + } + + @Override + public void customize(RuntimeWiring.Builder builder) { + builder.type("Query", wiring -> + wiring.dataFetcher("people", env -> this.service.findAll())); + } +} +---- + + +[[boot-repositories-querydsl]] +== Querydsl Repositories + +Spring Data repositories that extend `QuerydslPredicateExecutor` or +`ReactiveQuerydslPredicateExecutor` and are annotated with `@GraphQlRepository` are +detected and considered as candidates for `DataFetcher` +<> for matching top-level queries. + + + +[[boot-graphql-web]] +== Web Endpoints + +The GraphQL HTTP endpoint is at HTTP POST "/graphql" by default. The path can be customized: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +spring.graphql.path=/graphql +---- + +The GraphQL WebSocket endpoint supports WebSocket handshakes at "/graphql" by default. +The below shows the properties that apply for WebSocket handling: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +spring.graphql.websocket.path=/graphql + +# Time within which a "CONNECTION_INIT" message must be received from the client +spring.graphql.websocket.connection-init-timeout=60s +---- + +The GraphQL WebSocket endpoint is off by default. To enable it: + +- For a Servlet application, add the WebSocket starter `spring-boot-starter-websocket`. +- For a WebFlux application, set the `spring.graphql.websocket.path` application property. + +Declare a `WebInterceptor` bean to have it registered in the +<> for GraphQL over HTTP and WebSocket +requests. + +Declare a `ThreadLocalAccessor` bean to assist with the propagation of `ThreadLocal` +values of interest in <>. + + + +[[boot-graphql-graphiql]] +== GraphiQL + +The Spring Boot starter includes a https://github.com/graphql/graphiql[GraphiQL] page +that is exposed at "/graphiql" by default. You can configure this as follows: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +spring.graphql.graphiql.enabled=true +spring.graphql.graphiql.path=/graphiql +---- + + + + +[[boot-graphql-metrics]] +== Metrics + +When the starter `spring-boot-starter-actuator` is present on the classpath, metrics for +GraphQL requests are collected. You can disable metrics collection as follows: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +management.metrics.graphql.autotime.enabled=false +---- + +Metrics can be exposed with an Actuator web endpoint. +The following sections assume that its exposure is enabled in your application configuration, as follows: + +[source,properties,indent=0,subs="verbatim,quotes"] +---- +management.endpoints.web.exposure.include=health,metrics,info +---- + + +[[boot-graphql-metrics-request-timer]] +=== Request Timer + +A Request metric timer is available at `/actuator/metrics/graphql.request`. + +[cols="1,2,2"] +|=== +|Tag | Description| Sample values + +|outcome +|Request outcome +|"SUCCESS", "ERROR" +|=== + + +[[boot-graphql-metrics-datafetcher-timer]] +=== `DataFetcher` Timer + +A `DataFetcher` metric timer is available at `/actuator/metrics/graphql.datafetcher`. + +[cols="1,2,2"] +|=== +|Tag | Description| Sample values + +|path +|data fetcher path +|"Query.project" + +|outcome +|data fetching outcome +|"SUCCESS", "ERROR" +|=== + + +[[boot-graphql-metrics-error-counter]] +=== Error Counter + +A GraphQL error metric counter is available at `/actuator/metrics/graphql.error`. + +[cols="1,2,2"] +|=== +|Tag | Description| Sample values + +|errorType +|error type +|"DataFetchingException" + +|errorPath +|error JSON Path +|"$.project" +|=== + + + +[[boot-graphql-testing]] +== Testing + +For Spring GraphQL testing support, add the below to your classpath and that will make +a `WebGraphQlTester` available for injection into tests: + +[source,groovy,indent=0,subs="verbatim,quotes",role="primary"] +.Gradle +---- +dependencies { + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.graphql:spring-graphql-test:1.0.0-SNAPSHOT' + + // Also add this, unless `spring-boot-starter-webflux` is also present + testImplementation 'org.springframework:spring-webflux' + + // ... +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } // Spring milestones + maven { url 'https://repo.spring.io/snapshot' } // Spring snapshots +} +---- +[source,xml,indent=0,subs="verbatim,quotes",role="secondary"] +.Maven +---- + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.graphql + spring-graphql-test + 1.0.0-SNAPSHOT + test + + + + + org.springframework + spring-webflux + test + + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + +---- + +For GraphQL over HTTP with Spring MVC, using `MockMvc` as the server: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +@SpringBootTest +@AutoConfigureMockMvc +@AutoConfigureGraphQlTester +public class MockMvcGraphQlTests { + + @Autowired + private WebGraphQlTester graphQlTester; + +} +---- + +For GraphQL over HTTP with Spring WebFlux, using a +https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-mock-environment[mock server]: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +@SpringBootTest +@AutoConfigureWebTestClient +@AutoConfigureGraphQlTester +public class MockMvcGraphQlTests { + + @Autowired + private WebGraphQlTester graphQlTester; + +} +---- + +For GraphQL over HTTP with a +https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-running-server[running server]: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureGraphQlTester +public class MockMvcGraphQlTests { + + @Autowired + private WebGraphQlTester graphQlTester; + +} +---- + +Subscriptions can be tested without WebSocket as shown below: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +@SpringBootTest +@AutoConfigureGraphQlTester +public class MockMvcGraphQlTests { + + @Autowired + private WebGraphQlTester graphQlTester; + + @Test + void subscription() { + Flux result = this.graphQlTester.query("subscription { greetings }") + .executeSubscription() + .toFlux("greetings", String.class); + + // Use StepVerifier from "reactor-test" to verify the stream... + StepVerifier.create(result) + .expectNext("Hi") + .expectNext("Bonjour") + .expectNext("Hola") + .verifyComplete(); + } + +} +---- + +The above subscription test is performed directly against the `WebGraphQlHandler` that +both HTTP and WebSocket transports delegate to. It passes through the `WebInterceptor` +chain and then calls GraphQL Java which returns a Reactive Streams `Publisher`. diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index ce00d608..69712f20 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -611,428 +611,7 @@ cannot be used for integration test of GraphQL over WebSocket requests. -[[boot-graphql]] -== Boot Starter - -This projects builds on Boot 2.5.x, but it should be compatible with the latest Boot 2.4.x. - - - -[[boot-graphql-project]] -=== Project Setup - -To create a project, go to https://start.spring.io and select starter(s) for the -GraphQL transports you want to use: - -[cols="1,1,1"] -|=== -| Starter | Transport | Implementation - -| `spring-boot-starter-web` -| HTTP -| Spring MVC - -| `spring-boot-starter-websocket` -| WebSocket -| WebSocket for Servlet apps - -| `spring-boot-starter-webflux` -| HTTP, WebSocket -| Spring WebFlux - -|=== - -In the generated project, add `graphql-spring-boot-starter` manually: - -[source,groovy,indent=0,subs="verbatim,quotes",role="primary"] -.Gradle ----- -dependencies { - // Spring GraphQL Boot starter - implementation 'org.springframework.experimental:graphql-spring-boot-starter:1.0.0-SNAPSHOT' - - // ... -} - -repositories { - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } // Spring milestones - maven { url 'https://repo.spring.io/snapshot' } // Spring snapshots -} ----- -[source,xml,indent=0,subs="verbatim,quotes",role="secondary"] -.Maven ----- - - - // Spring GraphQL Boot starter - - org.springframework.experimental - graphql-spring-boot-starter - 1.0.0-SNAPSHOT - - - - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - ----- - -[NOTE] -.Boot Starter Group Id -==== -The Boot starter will move from the Spring GraphQL repository to the Spring Boot -repository, after Spring Boot 2.6 is released. The group id for the starter will then -change from `org.springframework.experimental` to `org.springframework.boot` and will be -released in Spring Boot 2.7. -==== - - - -[[boot-graphql-schema]] -=== Schema - -By default, GraphQL schema files are expected to be in `src/main/resources/graphql` and have -the extension ".graphqls", ".graphql", ".gql", or ".gqls". You can customize the -schema locations to check as follows: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -spring.graphql.schema.locations=classpath:graphql/ ----- - -The GraphQL schema can be viewed over HTTP at "/graphql/schema". This is not enabled by -default: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -spring.graphql.schema.printer.enabled=false ----- - - -[[boot-graphql-datafetcher]] -=== `DataFetcher` Registration - -You can declare `RuntimeWiringCustomizer` beans in your Spring config and use those to -register data fetchers, type resolvers, and more with the GraphQL engine: - -[source,java,indent=0,subs="verbatim,quotes"] ----- -@Component -public class PersonDataWiring implements RuntimeWiringCustomizer { - - private final PersonService service; - - public PersonDataWiring(PersonService service) { - this.service = service; - } - - @Override - public void customize(RuntimeWiring.Builder builder) { - builder.type("Query", wiring -> - wiring.dataFetcher("people", env -> this.service.findAll())); - } -} ----- - - -[[boot-repositories-querydsl]] -=== Querydsl Repositories - -Spring Data repositories that extend `QuerydslPredicateExecutor` or -`ReactiveQuerydslPredicateExecutor` and are annotated with `@GraphQlRepository` are -detected and considered as candidates for `DataFetcher` -<> for matching top-level queries. - - - -[[boot-graphql-web]] -=== Web Endpoints - -The GraphQL HTTP endpoint is at HTTP POST "/graphql" by default. The path can be customized: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -spring.graphql.path=/graphql ----- - -The GraphQL WebSocket endpoint supports WebSocket handshakes at "/graphql" by default. -The below shows the properties that apply for WebSocket handling: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -spring.graphql.websocket.path=/graphql - -# Time within which a "CONNECTION_INIT" message must be received from the client -spring.graphql.websocket.connection-init-timeout=60s ----- - -The GraphQL WebSocket endpoint is off by default. To enable it: - -- For a Servlet application, add the WebSocket starter `spring-boot-starter-websocket`. -- For a WebFlux application, set the `spring.graphql.websocket.path` application property. - -Declare a `WebInterceptor` bean to have it registered in the<> for -GraphQL over HTTP and WebSocket requests. - -Declare a `ThreadLocalAccessor` bean to assist with the propagation of `ThreadLocal` -values of interest in <>. - - - -[[boot-graphql-graphiql]] -=== GraphiQL - -The Spring Boot starter includes a https://github.com/graphql/graphiql[GraphiQL] page -that is exposed at "/graphiql" by default. You can configure this as follows: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -spring.graphql.graphiql.enabled=true -spring.graphql.graphiql.path=/graphiql ----- - - - - -[[boot-graphql-metrics]] -=== Metrics - -When the starter `spring-boot-starter-actuator` is present on the classpath, metrics for -GraphQL requests are collected. You can disable metrics collection as follows: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -management.metrics.graphql.autotime.enabled=false ----- - -Metrics can be exposed with an Actuator web endpoint. -The following sections assume that its exposure is enabled in your application configuration, as follows: - -[source,properties,indent=0,subs="verbatim,quotes"] ----- -management.endpoints.web.exposure.include=health,metrics,info ----- - - -[[boot-graphql-metrics-request-timer]] -==== Request Timer - -A Request metric timer is available at `/actuator/metrics/graphql.request`. - -[cols="1,2,2"] -|=== -|Tag | Description| Sample values - -|outcome -|Request outcome -|"SUCCESS", "ERROR" -|=== - - -[[boot-graphql-metrics-datafetcher-timer]] -==== `DataFetcher` Timer - -A `DataFetcher` metric timer is available at `/actuator/metrics/graphql.datafetcher`. - -[cols="1,2,2"] -|=== -|Tag | Description| Sample values - -|path -|data fetcher path -|"Query.project" - -|outcome -|data fetching outcome -|"SUCCESS", "ERROR" -|=== - - -[[boot-graphql-metrics-error-counter]] -==== Error Counter - -A GraphQL error metric counter is available at `/actuator/metrics/graphql.error`. - -[cols="1,2,2"] -|=== -|Tag | Description| Sample values - -|errorType -|error type -|"DataFetchingException" - -|errorPath -|error JSON Path -|"$.project" -|=== - - - -[[boot-graphql-testing]] -=== Testing - -For Spring GraphQL testing support, add the below to your classpath and that will make -a `WebGraphQlTester` available for injection into tests: - -[source,groovy,indent=0,subs="verbatim,quotes",role="primary"] -.Gradle ----- -dependencies { - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.graphql:spring-graphql-test:1.0.0-SNAPSHOT' - - // Also add this, unless `spring-boot-starter-webflux` is also present - testImplementation 'org.springframework:spring-webflux' - - // ... -} - -repositories { - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } // Spring milestones - maven { url 'https://repo.spring.io/snapshot' } // Spring snapshots -} ----- -[source,xml,indent=0,subs="verbatim,quotes",role="secondary"] -.Maven ----- - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.graphql - spring-graphql-test - 1.0.0-SNAPSHOT - test - - - - - org.springframework - spring-webflux - test - - - - - - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - ----- - -For GraphQL over HTTP with Spring MVC, using `MockMvc` as the server: - -[source,java,indent=0,subs="verbatim,quotes"] ----- -@SpringBootTest -@AutoConfigureMockMvc -@AutoConfigureGraphQlTester -public class MockMvcGraphQlTests { - - @Autowired - private WebGraphQlTester graphQlTester; - -} ----- - -For GraphQL over HTTP with Spring WebFlux, using a -https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-mock-environment[mock server]: - -[source,java,indent=0,subs="verbatim,quotes"] ----- -@SpringBootTest -@AutoConfigureWebTestClient -@AutoConfigureGraphQlTester -public class MockMvcGraphQlTests { - - @Autowired - private WebGraphQlTester graphQlTester; - -} ----- - -For GraphQL over HTTP with a -https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.with-running-server[running server]: - -[source,java,indent=0,subs="verbatim,quotes"] ----- -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@AutoConfigureGraphQlTester -public class MockMvcGraphQlTests { - - @Autowired - private WebGraphQlTester graphQlTester; - -} ----- - -Subscriptions can be tested without WebSocket as shown below: - -[source,java,indent=0,subs="verbatim,quotes"] ----- -@SpringBootTest -@AutoConfigureGraphQlTester -public class MockMvcGraphQlTests { - - @Autowired - private WebGraphQlTester graphQlTester; - - @Test - void subscription() { - Flux result = this.graphQlTester.query("subscription { greetings }") - .executeSubscription() - .toFlux("greetings", String.class); - - // Use StepVerifier from "reactor-test" to verify the stream... - StepVerifier.create(result) - .expectNext("Hi") - .expectNext("Bonjour") - .expectNext("Hola") - .verifyComplete(); - } - -} ----- - -The above subscription test is performed directly against the `WebGraphQlHandler` that -both HTTP and WebSocket transports delegate to. It passes through the `WebInterceptor` -chain and then calls GraphQL Java which returns a Reactive Streams `Publisher`. +include::boot-starter.adoc[leveloffset=+1]