Extract boot starter docs into a dedicated asciidoc file

This commit is contained in:
Rossen Stoyanchev
2021-07-21 14:30:58 +01:00
parent 69b2476231
commit 39702b9745
2 changed files with 424 additions and 422 deletions

View File

@@ -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
----
<dependencies>
// Spring GraphQL Boot starter
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- ... -->
</dependencies>
<!-- For Spring project milestones or snapshot releases -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
----
[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`
<<index.adoc#data-querydsl-registration,auto registration>> 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
<<index.adoc#web-interception,Web Interception>> for GraphQL over HTTP and WebSocket
requests.
Declare a `ThreadLocalAccessor` bean to assist with the propagation of `ThreadLocal`
values of interest in <<index.adoc#execution-context-webmvc,Spring MVC>>.
[[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
----
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<!-- Also add this, unless "spring-boot-starter-webflux" is also present -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<scope>test</scope>
</dependency>
<!-- ... -->
</dependencies>
<!-- For Spring project milestones or snapshot releases -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
----
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<String> 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`.

View File

@@ -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
----
<dependencies>
// Spring GraphQL Boot starter
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- ... -->
</dependencies>
<!-- For Spring project milestones or snapshot releases -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
----
[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`
<<data-querydsl-registration,auto registration>> 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<<web-interception>> for
GraphQL over HTTP and WebSocket requests.
Declare a `ThreadLocalAccessor` bean to assist with the propagation of `ThreadLocal`
values of interest in <<execution-context-webmvc>>.
[[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
----
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<!-- Also add this, unless "spring-boot-starter-webflux" is also present -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<scope>test</scope>
</dependency>
<!-- ... -->
</dependencies>
<!-- For Spring project milestones or snapshot releases -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
----
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<String> 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]