From 70afadc04a22c2a12ad5bda053728102f418ad9d Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Tue, 6 Dec 2022 14:39:45 +0100 Subject: [PATCH] Rewrite anchors in reference documentation This commit ensures that all anchors in the reference documentation follow a `"section.sub.title"`-like pattern to better align with the spring-asciidoctor-backends best practices. This will allow an easier integration with code snippets. All rewritten anchors are listed in the anchor-rewrite.properties file for automatic redirection. --- spring-graphql-docs/build.gradle | 2 +- .../docs/asciidoc/anchor-rewrite.properties | 68 ++++++ .../src/docs/asciidoc/attributes.adoc | 36 +-- .../docs/asciidoc/{ => includes}/client.adoc | 69 +++--- .../docs/asciidoc/{ => includes}/testing.adoc | 55 +++-- .../src/docs/asciidoc/index.adoc | 206 +++++++++--------- 6 files changed, 249 insertions(+), 187 deletions(-) create mode 100644 spring-graphql-docs/src/docs/asciidoc/anchor-rewrite.properties rename spring-graphql-docs/src/docs/asciidoc/{ => includes}/client.adoc (89%) rename spring-graphql-docs/src/docs/asciidoc/{ => includes}/testing.adoc (90%) diff --git a/spring-graphql-docs/build.gradle b/spring-graphql-docs/build.gradle index bab75151..97fe3e77 100644 --- a/spring-graphql-docs/build.gradle +++ b/spring-graphql-docs/build.gradle @@ -81,7 +81,7 @@ asciidoctor { configurations 'asciidoctorExtensions' baseDirFollowsSourceDir() sources { - include '*.adoc' + include 'index.adoc' } logDocuments = true outputOptions { diff --git a/spring-graphql-docs/src/docs/asciidoc/anchor-rewrite.properties b/spring-graphql-docs/src/docs/asciidoc/anchor-rewrite.properties new file mode 100644 index 00000000..925e451b --- /dev/null +++ b/spring-graphql-docs/src/docs/asciidoc/anchor-rewrite.properties @@ -0,0 +1,68 @@ +server-transports=server.transports +server-http=server.transports.http +server-websocket=server.transports.websocket +server-rsocket=server.transports.rsocket +execution-graphqlsource=execution.graphqlsource +execution-graphqlsource-schema-resources=execution.graphqlsource.schema-resources +execution-graphqlsource-schema-creation=execution.graphqlsource.schema-creation +execution-graphqlsource-schema-traversal=execution.graphqlsource.schema-traversal +execution-graphqlsource-schema-transformation=execution.graphqlsource.schema-transformation +execution-graphqlsource-runtimewiring-configurer=execution.graphqlsource.runtimewiring-configurer +execution-graphqlsource-default-type-resolver=execution.graphqlsource.default-type-resolver +execution-graphqlsource-operation-caching=execution.graphqlsource.operation-caching +execution-graphqlsource-directives=execution.graphqlsource.directives +execution-reactive-datafetcher=execution.reactive-datafetcher +execution-context=execution.context +execution-context-webmvc=execution.context.webmvc +execution-context-webflux=execution.context.webflux +execution-exceptions=execution.exceptions +execution-exceptions-request=execution.exceptions.request +execution-exceptions-subsctiption=execution.exceptions.subscription +execution-batching=execution.batching +execution-batching-dataloader=execution.batching.dataloader +execution-batching-batch-loader-registry=execution.batching.batch-loader-registry +execution-batching-testing=execution.batching.testing +data-querydsl=data.querydsl +data-querydsl-build=data.querydsl.build +data-querydsl-customizations=data.querydsl.customizations +data-querydsl-registration=data.querydsl.registration +data-querybyexample=data.querybyexample +data-querybyexample-build=data.querybyexample.build +data-querybyexample-customizations=data.querybyexample.customizations +data-querybyexample-registration=data.querybyexample.registration +data-projections=data.projections +controllers-schema-mapping=controllers.schema-mapping +controllers-schema-mapping-signature=controllers.schema-mapping.signature +controllers-schema-mapping-argument=controllers.schema-mapping.argument +controllers-schema-mapping-argument-value=controllers.schema-mapping.argument-value +controllers-schema-mapping-arguments=controllers.schema-mapping.arguments +controllers-schema-mapping-projectedpayload-argument=controllers.schema-mapping.projectedpayload.argument +controllers-schema-mapping-source=controllers.schema-mapping.source +controllers-schema-mapping-data-loader=controllers.schema-mapping.data-loader +controllers-schema-mapping-validation=controllers.schema-mapping.validation +controllers-batch-mapping=controllers.batch-mapping +controllers-batch-mapping-signature=controllers.batch-mapping.signature +client-graphqlclient=client.graphqlclient +client-httpgraphqlclient=client.httpgraphqlclient +client-websocketgraphqlclient=client.websocketgraphqlclient +client-websocketgraphqlclient-interceptor=client.websocketgraphqlclient.interceptor +client-rsocketgraphqlclient=client.rsocketgraphqlclient +client-graphqlclient-builder=client.graphqlclient.builder +client-requests=client.requests +client-requests-retrieve=client.requests.retrieve +client-requests-execute=client.requests.execute +client-requests-document-source=client.requests.document-source +client-subscriptions=client.subscriptions +client-subscriptions-retrieve=client.subscriptions.retrieve +client-subscriptions-execute=client.subscriptions.execute +client-interception=client.interception +testing-graphqltester=testing.graphqltester +testing-httpgraphqltester=testing.httpgraphqltester +testing-websocketgraphqltester=testing.websocketgraphqltester +testing-rsocketgraphqltester=testing.rsocketgraphqltester +testing-graphqlservicetester=testing.graphqlservicetester +testing-webgraphqltester=testing.webgraphqltester +testing-graphqltester-builder=testing.graphqltester.builder +testing-requests=testing.requests +testing-subscriptions=testing.subscriptions +testing-errors=testing.errors diff --git a/spring-graphql-docs/src/docs/asciidoc/attributes.adoc b/spring-graphql-docs/src/docs/asciidoc/attributes.adoc index 1d32dfa5..767690af 100644 --- a/spring-graphql-docs/src/docs/asciidoc/attributes.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/attributes.adoc @@ -1,22 +1,26 @@ +:chomp: default headers packages +:docs-site: https://docs.spring.io :idprefix: -:idseparator: - -:toc: left -:toclevels: 4 -:tabsize: 4 +:idseparator: - +:toc: left +:toclevels: 4 +:tabsize: 4 :numbered: :sectanchors: :sectnums: :hide-uri-scheme: -:github-tag: main -:github-repo: spring-projects/spring-graphql -:github-raw: https://raw.githubusercontent.com/{github-repo}/{github-tag} -:github-issues: https://github.com/{github-repo}/issues/ -:github-main-branch: https://github.com/{github-repo}/tree/main -:github-10x-branch: https://github.com/{github-repo}/tree/1.0.x -:github-wiki: https://github.com/{github-repo}/wiki -:graphql-java-docs: https://www.graphql-java.com/documentation -:javadoc: https://docs.spring.io/spring-graphql/docs/{spring-graphql-version}/api -:spring-framework-ref-docs: https://docs.spring.io/spring-framework/docs/current/reference/html - +:docs-java: {docdir}/../../main/java/org/springframework/graphql/docs +:docs-kotlin: {docdir}/../../main/kotlin/org/springframework/graphql/docs +:docs-resources: {docdir}/../../main/resources +:github-tag: main +:github-repo: spring-projects/spring-graphql +:github-raw: https://raw.githubusercontent.com/{github-repo}/{github-tag} +:github-issues: https://github.com/{github-repo}/issues/ +:github-main-branch: https://github.com/{github-repo}/tree/main +:github-10x-branch: https://github.com/{github-repo}/tree/1.0.x +:github-wiki: https://github.com/{github-repo}/wiki +:graphql-java-docs: https://www.graphql-java.com/documentation +:javadoc: https://docs.spring.io/spring-graphql/docs/{spring-graphql-version}/api +:spring-framework-ref-docs: https://docs.spring.io/spring-framework/docs/current/reference/html // {spring-boot-version} attribute from build.gradle -:spring-boot-ref-docs: https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/html \ No newline at end of file +:spring-boot-ref-docs: https://docs.spring.io/spring-boot/docs/{spring-boot-version}/reference/html \ No newline at end of file diff --git a/spring-graphql-docs/src/docs/asciidoc/client.adoc b/spring-graphql-docs/src/docs/asciidoc/includes/client.adoc similarity index 89% rename from spring-graphql-docs/src/docs/asciidoc/client.adoc rename to spring-graphql-docs/src/docs/asciidoc/includes/client.adoc index ea5b8480..d0dbecd3 100644 --- a/spring-graphql-docs/src/docs/asciidoc/client.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/includes/client.adoc @@ -1,8 +1,3 @@ -include::attributes.adoc[] - - - - [[client]] = Client @@ -11,7 +6,7 @@ WebSocket, and RSocket. -[[client-graphqlclient]] +[[client.graphqlclient]] == `GraphQlClient` `GraphQlClient` is a contract that declares a common workflow for GraphQL requests that is @@ -21,18 +16,18 @@ build time. To create a `GraphQlClient` you need one of the following extensions: -- <> -- <> -- <> +- <> +- <> +- <> Each defines a `Builder` with options relevant to the transport. All builders extend -from a common, base GraphQlClient <> with options +from a common, base GraphQlClient <> with options relevant to all extensions. -Once you have a `GraphQlClient` you can begin to make <>. +Once you have a `GraphQlClient` you can begin to make <>. -[[client-httpgraphqlclient]] +[[client.httpgraphqlclient]] === HTTP `HttpGraphQlClient` uses @@ -46,7 +41,7 @@ HttpGraphQlClient graphQlClient = HttpGraphQlClient.create(webClient); ---- Once `HttpGraphQlClient` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. If you need to change any transport specific details, use `mutate()` on an existing `HttpGraphQlClient` to create a new instance with customized settings: @@ -70,7 +65,7 @@ existing `HttpGraphQlClient` to create a new instance with customized settings: -[[client-websocketgraphqlclient]] +[[client.websocketgraphqlclient]] === WebSocket `WebSocketGraphQlClient` executes GraphQL requests over a shared WebSocket connection. @@ -102,7 +97,7 @@ single, shared connection for all requests to that server. Each client instance establishes its own connection and that is typically not the intent for a single server. Once `WebSocketGraphQlClient` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. If you need to change any transport specific details, use `mutate()` on an existing `WebSocketGraphQlClient` to create a new instance with customized settings: @@ -126,7 +121,7 @@ existing `WebSocketGraphQlClient` to create a new instance with customized setti ---- -[[client-websocketgraphqlclient-interceptor]] +[[client.websocketgraphqlclient.interceptor]] ==== Interceptor The https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md[GraphQL over WebSocket] @@ -154,13 +149,13 @@ For WebSocket transport specific interception, you can create a } ---- -<> the above interceptor as any other +<> the above interceptor as any other `GraphQlClientInterceptor` and use it also to intercept GraphQL requests, but note there can be at most one interceptor of type `WebSocketGraphQlClientInterceptor`. -[[client-rsocketgraphqlclient]] +[[client.rsocketgraphqlclient]] === RSocket `RSocketGraphQlClient` uses @@ -192,33 +187,33 @@ single, shared session for all requests to that server. Each client instance establishes its own connection and that is typically not the intent for a single server. Once `RSocketGraphQlClient` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. -[[client-graphqlclient-builder]] +[[client.graphqlclient.builder]] === Builder `GraphQlClient` defines a parent `Builder` with common configuration options for the builders of all extensions. Currently, it has lets you configure: - `DocumentSource` strategy to load the document for a request from a file -- <> of executed requests +- <> of executed requests -[[client-requests]] +[[client.requests]] == Requests -Once you have a <>, you can begin to perform requests via -<> or <> +Once you have a <>, you can begin to perform requests via +<> or <> where the former is only a shortcut for the latter. -[[client-requests-retrieve]] +[[client.requests.retrieve]] === Retrieve The below retrieves and decodes the data for a query: @@ -244,7 +239,7 @@ The below retrieves and decodes the data for a query: The input document is a `String` that could be a literal or produced through a code generated request object. You can also define documents in files and use a -<> to resole them by file name. +<> to resole them by file name. The path is relative to the "data" key and uses a simple dot (".") separated notation for nested fields with optional array indices for list elements, e.g. `"project.name"` @@ -269,10 +264,10 @@ response and the field: -[[client-requests-execute]] +[[client.requests.execute]] === Execute -<> is only a shortcut to decode from a single path in the +<> is only a shortcut to decode from a single path in the response map. For more control, use the `execute` method and handle the response: For example: @@ -307,7 +302,7 @@ For example: -[[client-requests-document-source]] +[[client.requests.document-source]] === Document Source The document for a request is a `String` that may be defined in a local variable or @@ -346,26 +341,26 @@ You can then: The "JS GraphQL" plugin for IntelliJ supports GraphQL query files with code completion. -You can use the `GraphQlClient` <> to customize the +You can use the `GraphQlClient` <> to customize the `DocumentSource` for loading documents by names. -[[client-subscriptions]] +[[client.subscriptions]] == Subscription Requests `GraphQlClient` can execute subscriptions over transports that support it. Currently, only the WebSocket transport supports GraphQL streams, so you'll need to create a -<>. +<>. -[[client-subscriptions-retrieve]] +[[client.subscriptions.retrieve]] === Retrieve To start a subscription stream, use `retrieveSubscription` which is similar to -<> for a single response but returning a stream of +<> for a single response but returning a stream of responses, each decoded to some data: [source,java,indent=0,subs="verbatim,quotes"] @@ -389,10 +384,10 @@ the connection and start the subscription again. -[[client-subscriptions-execute]] +[[client.subscriptions.execute]] === Execute -<> is only a shortcut to decode from a single path in each +<> is only a shortcut to decode from a single path in each response map. For more control, use the `executeSubscription` method and handle each response directly: @@ -422,7 +417,7 @@ response directly: -[[client-interception]] +[[client.interception]] == Interception You create a `GraphQlClientInterceptor` to intercept all requests through a client: diff --git a/spring-graphql-docs/src/docs/asciidoc/testing.adoc b/spring-graphql-docs/src/docs/asciidoc/includes/testing.adoc similarity index 90% rename from spring-graphql-docs/src/docs/asciidoc/testing.adoc rename to spring-graphql-docs/src/docs/asciidoc/includes/testing.adoc index c7700679..f609735a 100644 --- a/spring-graphql-docs/src/docs/asciidoc/testing.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/includes/testing.adoc @@ -1,8 +1,3 @@ -include::attributes.adoc[] - - - - [[testing]] = Testing @@ -36,7 +31,7 @@ dependencies { -[[testing-graphqltester]] +[[testing.graphqltester]] == `GraphQlTester` `GraphQlTester` is a contract that declares a common workflow for testing GraphQL @@ -47,22 +42,22 @@ specific is configured at build time. To create a `GraphQlTester` that performs requests through a client, you need one of the following extensions: -- <> -- <> -- <> +- <> +- <> +- <> To create a `GraphQlTester` that performs tests on the server side, without a client: -- <> -- <> +- <> +- <> Each defines a `Builder` with options relevant to the transport. All builders extend -from a common, base GraphQlTester <> with +from a common, base GraphQlTester <> with options relevant to all extensions. -[[testing-httpgraphqltester]] +[[testing.httpgraphqltester]] === HTTP `HttpGraphQlTester` uses @@ -114,7 +109,7 @@ Or to test against a live server running on a port: ---- Once `HttpGraphQlTester` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. If you need to change any transport specific details, use `mutate()` on an existing `HttpSocketGraphQlTester` to create a new instance with customized settings: @@ -136,7 +131,7 @@ existing `HttpSocketGraphQlTester` to create a new instance with customized sett -[[testing-websocketgraphqltester]] +[[testing.websocketgraphqltester]] === WebSocket `WebSocketGraphQlTester` executes GraphQL requests over a shared WebSocket connection. @@ -157,7 +152,7 @@ its own single, shared connection for all requests. Typically, you'll want to us instance only per server. Once `WebSocketGraphQlTester` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. If you need to change any transport specific details, use `mutate()` on an existing `WebSocketGraphQlTester` to create a new instance with customized settings: @@ -185,7 +180,7 @@ connection closed, e.g. after a test runs. -[[testing-rsocketgraphqltester]] +[[testing.rsocketgraphqltester]] === RSocket `RSocketGraphQlTester` uses `RSocketRequester` from spring-messaging to execute GraphQL @@ -207,11 +202,11 @@ instance only per server. You can use the `stop()` method on the tester to close session explicitly. Once `RSocketGraphQlTester` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. -[[testing-graphqlservicetester]] +[[testing.graphqlservicetester]] === `GraphQlService` Many times it's enough to test GraphQL requests on the server side, without the use of a @@ -225,14 +220,14 @@ client to send requests over a transport protocol. To test directly against a ---- Once `ExecutionGraphQlServiceTester` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. -[[testing-webgraphqltester]] +[[testing.webgraphqltester]] === `WebGraphQlHandler` -The <> extension lets you test on the server side, without +The <> extension lets you test on the server side, without a client. However, in some cases it's useful to involve server side transport handling with given mock transport input. @@ -258,12 +253,12 @@ The builder for this extension allows you to define HTTP request details: ---- Once `WebGraphQlServiceTester` is created, you can begin to -<> using the same API, independent of the underlying +<> using the same API, independent of the underlying transport. -[[testing-graphqltester-builder]] +[[testing.graphqltester.builder]] === Builder `GraphQlTester` defines a parent `Builder` with common configuration options for the @@ -279,7 +274,7 @@ out. -[[testing-requests]] +[[testing.requests]] == Requests Once you have a `GraphQlTester`, you can begin to test requests. The below executes a @@ -349,12 +344,12 @@ instead of `execute` to verify there are no errors in the response: graphQlTester.query(query).executeAndVerify(); ---- -See <> for more details on error handling. +See <> for more details on error handling. -[[testing-subscriptions]] +[[testing.subscriptions]] == Subscriptions To test subscriptions, call `executeSubscription` instead of `execute` to obtain a stream @@ -373,13 +368,13 @@ of responses and then use `StepVerifier` from Project Reactor to inspect the str .verifyComplete(); ---- -Subscriptions are supported only with <>, or with the server side -<> and <> extensions. +<> and <> extensions. -[[testing-errors]] +[[testing.errors]] == Errors When you use `verify()`, any errors under the "errors" key in the response will cause diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index b5cc0ec6..8b8a373f 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -27,18 +27,18 @@ The are also https://github.com/spring-projects/spring-graphql/tree/1.0.x/sample -[[server-transports]] +[[server.transports]] == Server Transports Spring for GraphQL supports server handling of GraphQL requests over HTTP, WebSocket, and RSocket. -[[server-http]] +[[server.transports.http]] === HTTP `GraphQlHttpHandler` handles GraphQL over HTTP requests and delegates to the -<> chain for request execution. There are two variants, one for +<> chain for request execution. There are two variants, one for Spring MVC and one for Spring WebFlux. Both handle requests asynchronously and have equivalent functionality, but rely on blocking vs non-blocking I/O respectively for writing the HTTP response. @@ -64,7 +64,7 @@ The 1.0.x branch of this repository contains a Spring MVC -[[server-websocket]] +[[server.transports.websocket]] === WebSocket `GraphQlWebSocketHandler` handles GraphQL over WebSocket requests based on the @@ -72,7 +72,7 @@ https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md[protocol] define https://github.com/enisdenjo/graphql-ws[graphql-ws] library. The main reason to use GraphQL over WebSocket is subscriptions which allow sending a stream of GraphQL responses, but it can also be used for regular queries with a single response. -The handler delegates every request to the <> chain for further +The handler delegates every request to the <> chain for further request execution. [TIP] @@ -108,7 +108,7 @@ The 1.0.x branch of this repository contains a WebFlux -[[server-rsocket]] +[[server.transports.rsocket]] === RSocket `GraphQlRSocketHandler` handles GraphQL over RSocket requests. Queries and mutations are @@ -145,17 +145,17 @@ public class GraphQlRSocketController { -[[server-interception]] +[[server.interception]] === Interception Server transports allow intercepting requests before and after the GraphQL Java engine is called to process a request. -[[server-interception-web]] +[[server.interception.web]] ==== `WebGraphQlInterceptor` -<> and <> transports invoke a chain of +<> and <> transports invoke a chain of 0 or more `WebGraphQlInterceptor`, followed by an `ExecutionGraphQlService` that calls the GraphQL Java engine. `WebGraphQlInterceptor` allows an application to intercept incoming requests and do one of the following: @@ -259,10 +259,10 @@ by the Boot starter, see {spring-boot-ref-docs}/web.html#web.graphql.transports.http-websocket[Web Endpoints]. -[[server-interception-rsocket]] +[[server.interception.rsocket]] ==== `RSocketQlInterceptor` -Similar to <>, an `RSocketQlInterceptor` allows intercepting +Similar to <>, an `RSocketQlInterceptor` allows intercepting GraphQL over RSocket requests before and after GraphQL Java engine execution. You can use this to customize the `graphql.ExecutionInput` and the `graphql.ExecutionResult`. @@ -273,7 +273,7 @@ this to customize the `graphql.ExecutionInput` and the `graphql.ExecutionResult` == Request Execution `ExecutionGraphQlService` is the main Spring abstraction to call GraphQL Java to execute -requests. Underlying transports, such as the <>, delegate to +requests. Underlying transports, such as the <>, delegate to `ExecutionGraphQlService` to handle requests. The main implementation, `DefaultExecutionGraphQlService`, is configured with a @@ -281,7 +281,7 @@ The main implementation, `DefaultExecutionGraphQlService`, is configured with a -[[execution-graphqlsource]] +[[execution.graphqlsource]] === `GraphQLSource` `GraphQlSource` is a contract to expose the `graphql.GraphQL` instance to use that also @@ -290,14 +290,14 @@ includes a builder API to build that instance. The default builder is available {spring-boot-ref-docs}/web.html#web.graphql[Spring Boot starter] creates an instance of this builder and further initializes it as follows: -- Loads <> from a configurable location. +- Loads <> from a configurable location. - Exposes {spring-boot-ref-docs}/application-properties.html#appendix.application-properties.web[properties] that apply to `GraphQlSource.Builder`. -- Detects <> beans. +- Detects <> beans. - Detects https://www.graphql-java.com/documentation/instrumentation[Instrumentation] beans for {spring-boot-ref-docs}/actuator.html#actuator.metrics.supported.spring-graphql[GraphQL metrics]. -- Detects `DataFetcherExceptionResolver` beans for <>. -- Detects `SubscriptionExceptionResolver` beans for <>. +- Detects `DataFetcherExceptionResolver` beans for <>. +- Detects `SubscriptionExceptionResolver` beans for <>. For further customizations, you can declare a `GraphQlSourceBuilderCustomizer` bean. For example, to configure your own `ExecutionIdProvider`: @@ -318,7 +318,7 @@ class GraphQlConfig { -[[execution-graphqlsource-schema-resources]] +[[execution.graphqlsource.schema-resources]] ==== Schema Resources `GraphQlSource.Builder` can be configured with one or more `Resource` instances to be @@ -336,7 +336,7 @@ TIP: Use `classpath*:graphql/**/` to find schema files across multiple classpath locations, e.g. across multiple modules. -[[execution-graphqlsource-schema-creation]] +[[execution.graphqlsource.schema-creation]] ==== Schema Creation By default, `GraphQlSource.Builder` uses the GraphQL Java `SchemaGenerator` to create the @@ -354,30 +354,30 @@ builder.schemaResources(..) }) ---- -The <> explains how to configure that with Spring Boot. +The <> explains how to configure that with Spring Boot. -[[execution-graphqlsource-schema-traversal]] +[[execution.graphqlsource.schema-traversal]] ==== Schema Traversal You can register a `graphql.schema.GraphQLTypeVisitor` via `builder.schemaResources(..).typeVisitors(..)` if you want to traverse the schema after it is created, and possibly apply changes to the `GraphQLCodeRegistry`. Keep in mind, however, that such a visitor cannot change the schema. See -<>, if you need to make changes to the schema. +<>, if you need to make changes to the schema. -[[execution-graphqlsource-schema-transformation]] +[[execution.graphqlsource.schema-transformation]] ==== Schema Transformation You can register a `graphql.schema.GraphQLTypeVisitor` via `builder.schemaResources(..).typeVisitorsToTransformSchema(..)` if you want to traverse and transform the schema after it is created, and make changes to the schema. Keep in mind -that this is more expensive than <> so generally +that this is more expensive than <> so generally prefer traversal to transformation unless you need to make schema changes. -[[execution-graphqlsource-runtimewiring-configurer]] +[[execution.graphqlsource.runtimewiring-configurer]] ==== `RuntimeWiringConfigurer` You can use `RuntimeWiringConfigurer` to register: @@ -385,7 +385,7 @@ You can use `RuntimeWiringConfigurer` to register: - Custom scalar types. - Directives handling code. - `TypeResolver`, if you need to override the - <> for a type. + <> for a type. - `DataFetcher` for a field, although most applications will simply configure `AnnotatedControllerConfigurer`, which detects annotated, `DataFetcher` handler methods. The Spring Boot starter adds the `AnnotatedControllerConfigurer` by default. @@ -423,12 +423,12 @@ schema definitions, implement the alternative `configure` method that accepts bo number of factories that are then invoked in sequence. -[[execution-graphqlsource-default-type-resolver]] +[[execution.graphqlsource.default-type-resolver]] ==== Default `TypeResolver` `GraphQlSource.Builder` registers `ClassNameTypeResolver` as the default `TypeResolver` to use for GraphQL Interfaces and Unions that don't already have such a registration -through a <>. The purpose of +through a <>. The purpose of a `TypeResolver` in GraphQL Java is to determine the GraphQL Object type for values returned from the `DataFetcher` for a GraphQL Interface or Union field. @@ -448,9 +448,9 @@ classNameTypeResolver.setClassNameExtractor((klass) -> { builder.defaultTypeResolver(classNameTypeResolver); ---- -The <> explains how to configure that with Spring Boot. +The <> explains how to configure that with Spring Boot. -[[execution-graphqlsource-operation-caching]] +[[execution.graphqlsource.operation-caching]] ==== Operation Caching GraphQL Java must _parse_ and _validate_ an operation before executing it. This may impact @@ -476,9 +476,9 @@ builder.schemaResources(..) .configureGraphQl(graphQLBuilder -> graphQLBuilder.preparsedDocumentProvider(provider)) ---- -The <> explains how to configure that with Spring Boot. +The <> explains how to configure that with Spring Boot. -[[execution-graphqlsource-directives]] +[[execution.graphqlsource.directives]] ==== Directives The GraphQL language supports directives that "describe alternate runtime execution and @@ -491,7 +491,7 @@ and handle directives. For more details, see GraphQL Java documentation. In Spring GraphQL you can register a `SchemaDirectiveWiring` through a -<>. The Spring Boot starter detects +<>. The Spring Boot starter detects such beans, so you might have something like: [source,java,indent=0,subs="verbatim,quotes"] @@ -513,7 +513,7 @@ library. -[[execution-reactive-datafetcher]] +[[execution.reactive-datafetcher]] === Reactive `DataFetcher` The default `GraphQlSource` builder enables support for a `DataFetcher` to return `Mono` @@ -524,25 +524,25 @@ GraphQL responses. A reactive `DataFetcher` can rely on access to Reactor context propagated from the transport layer, such as from a WebFlux request handling, see -<>. +<>. -[[execution-context]] +[[execution.context]] === Context Propagation Spring for GraphQL provides support to transparently propagate context from the -<>, through GraphQL Java, and to `DataFetcher` and other components it +<>, through GraphQL Java, and to `DataFetcher` and other components it invokes. This includes both `ThreadLocal` context from the Spring MVC request handling thread and Reactor `Context` from the WebFlux processing pipeline. -[[execution-context-webmvc]] +[[execution.context.webmvc]] ==== WebMvc A `DataFetcher` and other components invoked by GraphQL Java may not always execute on the same thread as the Spring MVC handler, for example if an asynchronous -<> or `DataFetcher` switches to a +<> or `DataFetcher` switches to a different thread. Spring for GraphQL supports propagating `ThreadLocal` values from the Servlet container @@ -583,23 +583,23 @@ You can register a `ThreadLocalAccessor` manually on startup with the global automatically through the `java.util.ServiceLoader` mechanism. -[[execution-context-webflux]] +[[execution.context.webflux]] ==== WebFlux -A <> can rely on access to Reactor context that +A <> can rely on access to Reactor context that originates from the WebFlux request handling chain. This includes Reactor context -added by <> components. +added by <> components. -[[execution-exceptions]] +[[execution.exceptions]] === Exception Resolution A GraphQL Java application can register a `DataFetcherExceptionHandler` to decide how to represent exceptions from the data layer in the "errors" section of the GraphQL response. Spring for GraphQL has a built-in `DataFetcherExceptionHandler` that is configured for use -by the default <> builder. It allows applications to register +by the default <> builder. It allows applications to register one or more Spring `DataFetcherExceptionResolver` components that are invoked sequentially until one resolves the `Exception` to a (possibly empty) list of `graphql.GraphQLError` objects. @@ -628,7 +628,7 @@ error details. Unresolved exception are logged at ERROR level along with the `executionId` to correlate to the error sent to the client. Resolved exceptions are logged at DEBUG level. -[[execution-exceptions-request]] +[[execution.exceptions.request]] ==== Request Exceptions The GraphQL Java engine may run into validation or other errors when parsing the request @@ -639,10 +639,10 @@ having a field path. `DataFetcherExceptionResolver` cannot handle such global errors because they are raised before execution begins and before any `DataFetcher` is invoked. An application can use transport level interceptors to inspect and transform errors in the `ExecutionResult`. -See examples under <>. +See examples under <>. -[[execution-exceptions-subsctiption]] +[[execution.exceptions.subscription]] ==== Subscription Exceptions The `Publisher` for a subscription request may complete with an error signal in which case @@ -659,7 +659,7 @@ to send to the client. -[[execution-batching]] +[[execution.batching]] === Batch Loading Given a `Book` and its `Author`, we can create one `DataFetcher` for a book and another @@ -669,7 +669,7 @@ books as the author for each book is loaded individually. This is known as the N problem. -[[execution-batching-dataloader]] +[[execution.batching.dataloader]] ==== `DataLoader` GraphQL Java provides a `DataLoader` mechanism for batch loading of related entities. @@ -684,7 +684,7 @@ summary of how it works: improve efficiency. -[[execution-batching-batch-loader-registry]] +[[execution.batching.batch-loader-registry]] ==== `BatchLoaderRegistry` The complete batching loading mechanism in GraphQL Java requires implementing one of @@ -719,7 +719,7 @@ register batch loading functions. In turn the `BatchLoaderRegistry` is injected By default, the `DataLoader` name is based on the class name of the target entity. This allows an `@SchemaMapping` method to declare a -<> with a generic type, and +<> with a generic type, and without the need for specifying a name. The name, however, can be customized through the `BatchLoaderRegistry` builder, if necessary, along with other `DataLoaderOptions`. @@ -728,17 +728,17 @@ registration, you can override Boot's `BatchLoaderRegistry` bean and use the con for `DefaultBatchLoaderRegistry` that accepts `Supplier`. For many cases, when loading related entities, you can use -<> controller methods, which are a shortcut +<> controller methods, which are a shortcut for and replace the need to use `BatchLoaderRegistry` and `DataLoader` directly. `BatchLoaderRegistry` provides other important benefits too. It supports access to the same `GraphQLContext` from batch loading functions and from `@BatchMapping` methods, -as well as ensures <> to them. This is why applications are expected +as well as ensures <> to them. This is why applications are expected to use it. It is possible to perform your own `DataLoader` registrations directly but such registrations would forgo the above benefits. -[[execution-batching-testing]] +[[execution.batching.testing]] ==== Testing Batch Loading Start by having `BatchLoaderRegistry` perform registrations on a `DataLoaderRegistry`: @@ -782,7 +782,7 @@ with `@GraphQlRepository`. -[[data-querydsl]] +[[data.querydsl]] === Querydsl Spring for GraphQL supports use of http://www.querydsl.com/[Querydsl] to fetch data through @@ -814,7 +814,7 @@ Then use it to create a `DataFetcher`: ---- You can now register the above `DataFetcher` through a -<>. +<>. The `DataFetcher` builds a Querydsl `Predicate` from GraphQL request parameters, and uses it to fetch data. Spring Data supports `QuerydslPredicateExecutor` for JPA, @@ -825,7 +825,7 @@ If the repository is `ReactiveQuerydslPredicateExecutor`, the builder returns variant for MongoDB. -[[data-querydsl-build]] +[[data.querydsl.build]] ==== Build Setup To configure Querydsl in your build, follow the @@ -896,7 +896,7 @@ The {github-10x-branch}/samples/webmvc-http[webmvc-http] sample uses Querydsl fo `artifactRepositories`. -[[data-querydsl-customizations]] +[[data.querydsl.customizations]] ==== Customizations `QuerydslDataFetcher` supports customizing how GraphQL arguments are bound onto properties @@ -905,7 +905,7 @@ each available property. To customize that, you can use `QuerydslDataFetcher` bu methods to provide a `QuerydslBinderCustomizer`. A repository may itself be an instance of `QuerydslBinderCustomizer`. This is auto-detected -and transparently applied during <>. However, when manually +and transparently applied during <>. However, when manually building a `QuerydslDataFetcher` you will need to use builder methods to apply it. `QuerydslDataFetcher` supports interface and DTO projections to transform query results @@ -913,7 +913,7 @@ before returning these for further GraphQL processing. TIP: To learn what projections are, please refer to the https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[Spring Data docs]. -To understand how to use projections in GraphQL, please see <>. +To understand how to use projections in GraphQL, please see <>. To use Spring Data projections with Querydsl repositories, create either a projection interface or a target DTO class and configure it through the `projectAs` method to obtain a @@ -946,7 +946,7 @@ or a target DTO class and configure it through the `projectAs` method to obtain -[[data-querydsl-registration]] +[[data.querydsl.registration]] ==== Auto-Registration If a repository is annotated with `@GraphQlRepository`, it is automatically registered @@ -967,13 +967,13 @@ obtained from `QuerydslDataFetcher`. The detects `@GraphQlRepository` beans and uses them to initialize the `RuntimeWiringConfigurer` with. -Auto-registration applies <> +Auto-registration applies <> by calling `customize(Builder)` on the repository instance if your repository implements `QuerydslBuilderCustomizer` or `ReactiveQuerydslBuilderCustomizer` respectively. -[[data-querybyexample]] +[[data.querybyexample]] === Query by Example Spring Data supports the use of @@ -1004,7 +1004,7 @@ Use `QueryByExampleDataFetcher` to turn the repository into a `DataFetcher`: ---- You can now register the above `DataFetcher` through a -<>. +<>. The `DataFetcher` uses the GraphQL arguments map to create the domain type of the repository and use that as the example object to fetch data with. Spring Data supports @@ -1015,14 +1015,14 @@ If the repository is `ReactiveQueryByExampleExecutor`, the builder returns variant for MongoDB, Neo4j, Redis, and R2dbc. -[[data-querybyexample-build]] +[[data.querybyexample.build]] ==== Build Setup Query by Example is already included in the Spring Data modules for the data stores where it is supported, so no extra setup is required to enable it. -[[data-querybyexample-customizations]] +[[data.querybyexample.customizations]] ==== Customizations `QueryByExampleDataFetcher` supports interface and DTO projections to transform query @@ -1030,7 +1030,7 @@ results before returning these for further GraphQL processing. TIP: To learn what projections are, please refer to the https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections[Spring Data documentation]. -To understand the role of projections in GraphQL, please see <>. +To understand the role of projections in GraphQL, please see <>. To use Spring Data projections with Query by Example repositories, create either a projection interface or a target DTO class and configure it through the `projectAs` method to obtain a @@ -1062,7 +1062,7 @@ or a target DTO class and configure it through the `projectAs` method to obtain ---- -[[data-querybyexample-registration]] +[[data.querybyexample.registration]] ==== Auto-Registration If a repository is annotated with `@GraphQlRepository`, it is automatically registered @@ -1080,14 +1080,14 @@ obtained from `QueryByExampleDataFetcher`. The detects `@GraphQlRepository` beans and uses them to initialize the `RuntimeWiringConfigurer` with. -Auto-registration applies <> +Auto-registration applies <> by calling `customize(Builder)` on the repository instance if your repository implements `QueryByExampleBuilderCustomizer` or `ReactiveQueryByExampleBuilderCustomizer` respectively. -[[data-projections]] +[[data.projections]] === Selection Set vs Projections A common question that arises is, how GraphQL selection sets compare to @@ -1109,7 +1109,7 @@ aggregate functionality. In Spring Data you can choose whether you want your aggregate be exposed as is, or whether to apply transformations to the data model before returning it as a GraphQL result. Sometimes it's enough to do the former, and by default the -<> and the <> integrations turn the GraphQL +<> and the <> integrations turn the GraphQL selection set into property path hints that the underlying Spring Data module uses to limit the selection. @@ -1187,7 +1187,7 @@ support for annotated ``DataFetcher``s, see the in the Boot starter documentation. -[[controllers-schema-mapping]] +[[controllers.schema-mapping]] === `@SchemaMapping` The `@SchemaMapping` annotation maps a handler method to a field in the GraphQL schema @@ -1268,7 +1268,7 @@ for fields under the Query, Mutation, and Subscription types respectively. For e method arguments and return values.. -[[controllers-schema-mapping-signature]] +[[controllers.schema-mapping.signature]] ==== Method Signature Schema mapping handler methods can have any of the following method arguments: @@ -1279,7 +1279,7 @@ Schema mapping handler methods can have any of the following method arguments: | `@Argument` | For access to a named field argument bound to a higher-level, typed Object. -See <>. +See <>. | `@Argument Map` | For access to the raw map of arguments, where `@Argument` does not have a @@ -1288,26 +1288,26 @@ See <>. | `ArgumentValue` | For access to a named field argument bound to a higher-level, typed Object along with a flag to indicate if the input argument was omitted vs set to `null`. -See <>. +See <>. | `@Arguments` | For access to all field arguments bound to a higher-level, typed Object. -See <>. +See <>. | `@Arguments Map` | For access to the raw map of arguments. | `@ProjectedPayload` Interface | For access to field arguments through a project interface. -See <>. +See <>. | "Source" | For access to the source (i.e. parent/container) instance of the field. -See <>. +See <>. | `DataLoader` | For access to a `DataLoader` in the `DataLoaderRegistry`. -See <>. +See <>. | `@ContextValue` | For access to an attribute from the main `GraphQLContext` in `DataFetchingEnvironment`. @@ -1339,12 +1339,12 @@ Schema mapping handler methods can return: - A resolved value of any type. - `Mono` and `Flux` for asynchronous value(s). Supported for controller methods and for - any `DataFetcher` as described in <>. + any `DataFetcher` as described in <>. - `java.util.concurrent.Callable` to have the value(s) produced asynchronously. For this to work, `AnnotatedControllerConfigurer` must be configured with an `Executor`. -[[controllers-schema-mapping-argument]] +[[controllers.schema-mapping.argument]] ==== `@Argument` In GraphQL Java, `DataFetchingEnvironment` provides access to a map of field-specific @@ -1390,13 +1390,13 @@ You can use `@Argument` with a `Map` argument, to obtain the raw all argument values. The name attribute on `@Argument` must not be set. -[[controllers-schema-mapping-argument-value]] +[[controllers.schema-mapping.argument-value]] ==== `ArgumentValue` By default, input arguments in GraphQL are nullable and optional, which means an argument can be set to the `null` literal, or not provided at all. This distinction is useful for partial updates with a mutation where the underlying data may also be, either set to -`null` or not changed at all accordingly. When using <> +`null` or not changed at all accordingly. When using <> there is no way to make such a distinction, because you would get `null` or an empty `Optional` in both cases. @@ -1428,7 +1428,7 @@ method parameter, either initialized via a constructor argument or via a setter, as a field of an object nested at any level below the top level object. -[[controllers-schema-mapping-arguments]] +[[controllers.schema-mapping.arguments]] ==== `@Arguments` Use the `@Arguments` annotation, if you want to bind the full arguments map onto a single @@ -1442,10 +1442,10 @@ You can use `@Arguments` with a `Map` argument, to obtain the ra all argument values. -[[controllers-schema-mapping-projectedpayload-argument]] +[[controllers.schema-mapping.projectedpayload.argument]] ==== `@ProjectedPayload` Interface -As an alternative to using complete Objects with <>, +As an alternative to using complete Objects with <>, you can also use a projection interface to access GraphQL request arguments through a well-defined, minimal interface. Argument projections are provided by https://docs.spring.io/spring-data/commons/docs/current/reference/html/#projections.interfaces[Spring Data's Interface projections] @@ -1493,7 +1493,7 @@ For example: -[[controllers-schema-mapping-source]] +[[controllers.schema-mapping.source]] ==== Source In GraphQL Java, the `DataFetchingEnvironment` provides access to the source (i.e. @@ -1518,16 +1518,16 @@ explicitly specify the type name in the `@SchemaMapping` annotation. [TIP] ==== -A <> handler method can batch load all authors for a query, +A <> handler method can batch load all authors for a query, given a list of source/parent books objects. ==== -[[controllers-schema-mapping-data-loader]] +[[controllers.schema-mapping.data-loader]] ==== `DataLoader` When you register a batch loading function for an entity, as explained in -<>, you can access the `DataLoader` for the entity by declaring a +<>, you can access the `DataLoader` for the entity by declaring a method argument of type `DataLoader` and use it to load the entity: [source,java,indent=0,subs="verbatim,quotes"] @@ -1558,10 +1558,10 @@ be necessary. Note that for many cases with loading related entities, where the `@SchemaMapping` simply delegates to a `DataLoader`, you can reduce boilerplate by using a -<> method as described in the next section. +<> method as described in the next section. -[[controllers-schema-mapping-validation]] +[[controllers.schema-mapping.validation]] ==== Validation When a `javax.validation.Validator` bean is found, `AnnotatedControllerConfigurer` enables support for @@ -1599,15 +1599,15 @@ method invocation: ---- If an error occurs during validation, a `ConstraintViolationException` is raised. -You can use the <> chain to decide how to present that to clients +You can use the <> chain to decide how to present that to clients by turning it into an error to include in the GraphQL response. TIP: In addition to `@Valid`, you can also use Spring's `@Validated` that allows specifying validation groups. -Bean validation is useful for <>, -<>, and -<> +Bean validation is useful for <>, +<>, and +<> method parameters, but applies more generally to any method parameter. [WARNING] @@ -1621,10 +1621,10 @@ for links to relevant issues and a suggested workaround. -[[controllers-batch-mapping]] +[[controllers.batch-mapping]] === `@BatchMapping` -<> addresses the N+1 select problem through the use of an +<> addresses the N+1 select problem through the use of an `org.dataloader.DataLoader` to defer the loading of individual entity instances, so they can be loaded together. For example: @@ -1679,7 +1679,7 @@ annotation attributes. The type name can also be inherited from a class level `@SchemaMapping`. -[[controllers-batch-mapping-signature]] +[[controllers.batch-mapping.signature]] ==== Method Signature Batch mapping methods support the following arguments: @@ -1737,14 +1737,14 @@ Batch mapping methods can return: [[security]] == Security -The path to a <> GraphQL endpoint can be secured with HTTP +The path to a <> GraphQL endpoint can be secured with HTTP URL security to ensure that only authenticated users can access it. This does not, however, differentiate among different GraphQL requests on such a shared endpoint on a single URL. To apply more fine-grained security, add Spring Security annotations such as `@PreAuthorize` or `@Secured` to service methods involved in fetching specific parts of -the GraphQL response. This should work due to <> that aims to make +the GraphQL response. This should work due to <> that aims to make Security, and other context, available at the data fetching level. The 1.0.x branch of this repository contains samples for @@ -1754,12 +1754,12 @@ The 1.0.x branch of this repository contains samples for -include::client.adoc[leveloffset=+1] +include::includes/client.adoc[leveloffset=+1] -include::testing.adoc[leveloffset=+1] +include::includes/testing.adoc[leveloffset=+1]