diff --git a/spring-graphql-docs/.github/workflows/deploy-docs.yml b/spring-graphql-docs/.github/workflows/deploy-docs.yml new file mode 100644 index 000000000..1435fc217 --- /dev/null +++ b/spring-graphql-docs/.github/workflows/deploy-docs.yml @@ -0,0 +1,33 @@ +name: Deploy Docs +on: + push: + branches-ignore: [ gh-pages ] + tags: '**' + repository_dispatch: + types: request-build-reference # legacy + #schedule: + #- cron: '0 10 * * *' # Once per day at 10am UTC + workflow_dispatch: +permissions: + actions: write +jobs: + build: + runs-on: ubuntu-latest + # FIXME enable when pushed to spring-projects + # if: github.repository_owner == 'spring-projects' + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: docs-build + fetch-depth: 1 + - name: Dispatch (partial build) + if: github.ref_type == 'branch' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }} + - name: Dispatch (full build) + if: github.ref_type == 'tag' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) diff --git a/spring-graphql-docs/antora-playbook.yml b/spring-graphql-docs/antora-playbook.yml new file mode 100644 index 000000000..6d3617e88 --- /dev/null +++ b/spring-graphql-docs/antora-playbook.yml @@ -0,0 +1,41 @@ +antora: + extensions: + - '@springio/antora-extensions/partial-build-extension' + # - require: '@springio/antora-extensions/latest-version-extension' + - require: '@springio/antora-extensions/inject-collector-cache-config-extension' + - '@antora/collector-extension' + - '@antora/atlas-extension' + - require: '@springio/antora-extensions/root-component-extension' + root_component_name: 'graphql' +site: + title: Spring GraphQL + url: https://rwinch.github.io/spring-graphql + robots: allow +git: + ensure_git_suffix: false +content: + sources: + - url: ./.. + branches: HEAD + start_path: spring-graphql-docs + worktrees: true +asciidoc: + attributes: + page-stackoverflow-url: https://stackoverflow.com/tags/spring-graphql + page-pagination: '' + hide-uri-scheme: '@' + tabs-sync-option: '@' + extensions: + - '@asciidoctor/tabs' + - '@springio/asciidoctor-extensions' +urls: + latest_version_segment_strategy: redirect:to + latest_version_segment: '' + redirect_facility: httpd +ui: + bundle: + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.3/ui-bundle.zip + snapshot: true +runtime: + log: + failure_level: warn diff --git a/spring-graphql-docs/antora.yml b/spring-graphql-docs/antora.yml new file mode 100644 index 000000000..5663081e2 --- /dev/null +++ b/spring-graphql-docs/antora.yml @@ -0,0 +1,31 @@ +name: graphql +version: true +title: Spring GraphQL +nav: + - modules/ROOT/nav.adoc +ext: + collector: + run: + command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError" :spring-graphql-docs:generateAntoraYml + local: true + scan: + dir: ./build/generated-antora-resources + +asciidoc: + attributes: + attribute-missing: 'warn' + chomp: 'all' + docs-site: https://docs.spring.io + include-java: 'example$docs-src/main/java/org/springframework/graphql/docs' + 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 + # version attributes from main build.gradle + spring-framework-ref-docs: https://docs.spring.io/spring-framework/reference + 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/build.gradle b/spring-graphql-docs/build.gradle index d4fa3bd98..a0f7c147c 100644 --- a/spring-graphql-docs/build.gradle +++ b/spring-graphql-docs/build.gradle @@ -1,6 +1,7 @@ plugins { id 'java-library' - id 'org.asciidoctor.jvm.convert' version '3.3.2' + id 'org.antora' version '1.0.0' + id 'io.spring.antora.generate-antora-yml' version '0.0.1' } description = "Spring for GraphQL reference documentation" @@ -12,7 +13,6 @@ configurations { visible = false } matching { it.name.endsWith("Classpath") }.all { it.extendsFrom(dependencyManagement) } - asciidoctorExtensions } dependencies { @@ -25,7 +25,6 @@ dependencies { api 'org.springframework:spring-messaging' api 'org.springframework.data:spring-data-commons' api 'com.querydsl:querydsl-core' - asciidoctorExtensions 'io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.4' } jar { @@ -77,42 +76,44 @@ task api(type: Javadoc) { destinationDir = file("$buildDir/docs/javadoc") } +antora { + version = '3.2.0-alpha.2' + options = [clean: true, fetch: !project.gradle.startParameter.offline, stacktrace: true] + environment = [ + 'ALGOLIA_API_KEY': '9d489079e5ec46dbb238909fee5c9c29', + 'ALGOLIA_APP_ID': 'WB1FQYI187', + 'ALGOLIA_INDEX_NAME': 'springsecurity', + ] + dependencies = [ + '@antora/atlas-extension': '1.0.0-alpha.1', + '@antora/collector-extension': '1.0.0-alpha.3', + '@asciidoctor/tabs': '1.0.0-beta.3', + '@springio/antora-extensions': '1.4.2', + '@springio/asciidoctor-extensions': '1.0.0-alpha.8', + '@opendevise/antora-release-line-extension': '1.0.0', + ] +} -/** - * Generate the Spring for GraphQL Reference documentation from "src/docs/asciidoc" - * in "build/docs/reference/html". - */ -asciidoctor { - configurations 'asciidoctorExtensions' - baseDirFollowsSourceDir() - sources { - include 'index.adoc' - } - logDocuments = true - outputOptions { - backends "spring-html" - } - outputDir "$buildDir/docs/reference/html" - attributes 'spring-graphql-version': project.version, - 'spring-boot-version': springBootVersion, - 'spring-framework-version': springFrameworkVersion +tasks.named("generateAntoraYml") { + asciidocAttributes = project.provider( { ['spring-graphql-version': project.version, + 'spring-boot-version': springBootVersion, + 'spring-framework-version': springFrameworkVersion] } ) } -asciidoctor.mustRunAfter "check" +tasks.named("antora") { + mustRunAfter "check" +} /** * Zip all docs into a single archive */ -task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor']) { +task docsZip(type: Zip, dependsOn: ['api']) { group = "Distribution" description = "Builds -${archiveClassifier} archive containing api and reference " + "for deployment at https://docs.spring.io/spring-graphql/docs." from (api) { into "api" } - from ("$asciidoctor.outputDir") { - into "reference/html" - } } publishing { diff --git a/spring-graphql-docs/modules/ROOT/examples/docs-src b/spring-graphql-docs/modules/ROOT/examples/docs-src new file mode 120000 index 000000000..a1d005e30 --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/examples/docs-src @@ -0,0 +1 @@ +../../../src/ \ No newline at end of file diff --git a/spring-graphql-docs/modules/ROOT/nav.adoc b/spring-graphql-docs/modules/ROOT/nav.adoc new file mode 100644 index 000000000..d503f51e7 --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/nav.adoc @@ -0,0 +1,13 @@ +* xref:index.adoc[Overview] +* xref:transports.adoc[] +* xref:request-execution.adoc[] +* xref:data.adoc[] +* xref:controllers.adoc[] +* xref:security.adoc[] +* xref:observability.adoc[] +* xref:graalvm-native.adoc[] +* xref:client.adoc[] +* xref:graphiql.adoc[] +* xref:testing.adoc[] +* xref:boot-starter.adoc[] +* xref:samples.adoc[] diff --git a/spring-graphql-docs/modules/ROOT/pages/boot-starter.adoc b/spring-graphql-docs/modules/ROOT/pages/boot-starter.adoc new file mode 100644 index 000000000..dfd8bf304 --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/pages/boot-starter.adoc @@ -0,0 +1,21 @@ +[[boot-starter]] += Boot Starter + +Spring Boot provides a starter for building GraphQL applications with Spring for GraphQL. +For version information, see the +https://github.com/spring-projects/spring-graphql/wiki/Spring-for-GraphQL-Versions[Spring for GraphQL Versions] wiki page. + +The easiest way to get started is via https://start.spring.io by selecting +"Spring for GraphQL" along with an underlying transport such as Spring MVC of WebFlux over +HTTP or WebSocket, or over RSocket. Refer to the +https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.graphql[Spring for GraphQL Starter] +section in the Spring Boot reference for details on supported transports, auto-configuration related +features, and more. For testing support, see +https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.testing.spring-boot-applications.spring-graphql-tests[Auto-Configured GraphQL Tests]. + +For further reference, check the following GraphQL related: + +- https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.supported.spring-graphql[Metrics] +- https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties.web[Properties] +- https://docs.spring.io/spring-boot/docs/current/reference/html/auto-configuration-classes.html#appendix.auto-configuration-classes.core[Auto-Configuration Classes] + diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/client.adoc b/spring-graphql-docs/modules/ROOT/pages/client.adoc similarity index 88% rename from spring-graphql-docs/src/docs/asciidoc/includes/client.adoc rename to spring-graphql-docs/modules/ROOT/pages/client.adoc index 4b5be98fb..607553a3d 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/client.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/client.adoc @@ -16,15 +16,15 @@ build time. To create a `GraphQlClient` you need one of the following extensions: -- <> -- <> -- <> +- xref:client.adoc#client.httpgraphqlclient[HttpGraphQlClient] +- xref:client.adoc#client.websocketgraphqlclient[WebSocketGraphQlClient] +- xref:client.adoc#client.rsocketgraphqlclient[RSocketGraphQlClient] 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 xref:client.adoc#client.graphqlclient.builder[`Builder`] 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 xref:client.adoc#client.requests[requests]. [[client.httpgraphqlclient]] @@ -41,7 +41,7 @@ HttpGraphQlClient graphQlClient = HttpGraphQlClient.create(webClient); ---- Once `HttpGraphQlClient` is created, you can begin to -<> using the same API, independent of the underlying +xref:client.adoc#client.requests[execute requests] 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: @@ -97,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 +xref:client.adoc#client.requests[execute requests] 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: @@ -149,7 +149,7 @@ For WebSocket transport specific interception, you can create a } ---- -<> the above interceptor as any other +xref:client.adoc#client.interception[Register] 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`. @@ -187,7 +187,7 @@ 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 +xref:client.adoc#client.requests[execute requests] using the same API, independent of the underlying transport. @@ -199,7 +199,7 @@ transport. 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 +- xref:client.adoc#client.interception[Interception] of executed requests @@ -207,8 +207,8 @@ builders of all extensions. Currently, it has lets you configure: [[client.requests]] == Requests -Once you have a <>, you can begin to perform requests via -<> or <> +Once you have a xref:client.adoc#client.graphqlclient[`GraphQlClient`], you can begin to perform requests via +xref:client.adoc#client.requests.retrieve[retrieve()] or xref:client.adoc#client.requests.execute[execute()] where the former is only a shortcut for the latter. @@ -239,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. +xref:client.adoc#client.requests.document-source[Document Source] 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"` @@ -267,7 +267,7 @@ response and the field: [[client.requests.execute]] === Execute -<> is only a shortcut to decode from a single path in the +xref:client.adoc#client.requests.retrieve[Retrieve] 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: @@ -341,7 +341,7 @@ 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` xref:client.adoc#client.graphqlclient.builder[Builder] to customize the `DocumentSource` for loading documents by names. @@ -352,8 +352,8 @@ You can use the `GraphQlClient` <> to customize th `GraphQlClient` can execute subscriptions over transports that support it. Only the WebSocket and RSocket transports support GraphQL subscriptions, so you'll need to -create a <> or -<>. +create a xref:client.adoc#client.websocketgraphqlclient[WebSocketGraphQlClient] or +xref:client.adoc#client.rsocketgraphqlclient[RSocketGraphQlClient]. @@ -361,7 +361,7 @@ create a <> or === Retrieve To start a subscription stream, use `retrieveSubscription` which is similar to -<> for a single response but returning a stream of +xref:client.adoc#client.requests.retrieve[retrieve] for a single response but returning a stream of responses, each decoded to some data: [source,java,indent=0,subs="verbatim,quotes"] @@ -390,7 +390,7 @@ provides access to the `Subscription`. [[client.subscriptions.execute]] === Execute -<> is only a shortcut to decode from a single path in each +xref:client.adoc#client.subscriptions.retrieve[Retrieve] 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: diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/controllers.adoc b/spring-graphql-docs/modules/ROOT/pages/controllers.adoc similarity index 87% rename from spring-graphql-docs/src/docs/asciidoc/includes/controllers.adoc rename to spring-graphql-docs/modules/ROOT/pages/controllers.adoc index 4f7d5be35..754f34170 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/controllers.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/controllers.adoc @@ -36,7 +36,7 @@ class, indicating its role as a data fetching component in a GraphQL application `AnnotatedControllerConfigurer` detects `@Controller` beans and registers their annotated handler methods as ``DataFetcher``s via `RuntimeWiring.Builder`. It is an implementation of `RuntimeWiringConfigurer` which can be added to `GraphQlSource.Builder`. -The <> automatically declares `AnnotatedControllerConfigurer` as a bean +The xref:boot-starter.adoc[Boot Starter] automatically declares `AnnotatedControllerConfigurer` as a bean and adds all `RuntimeWiringConfigurer` beans to `GraphQlSource.Builder` and that enables support for annotated ``DataFetcher``s, see the {spring-boot-ref-docs}/web.html#web.graphql.runtimewiring[GraphQL RuntimeWiring] section @@ -136,23 +136,23 @@ 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 xref:controllers.adoc#controllers.schema-mapping.argument[`@Argument`]. | `@Argument Map` | For access to the raw argument value. -See <>. +See xref:controllers.adoc#controllers.schema-mapping.argument[`@Argument`]. | `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 xref:controllers.adoc#controllers.schema-mapping.argument-value[`ArgumentValue`]. | `@Arguments` | For access to all field arguments bound to a higher-level, typed Object. -See <>. +See xref:controllers.adoc#controllers.schema-mapping.arguments[`@Arguments`]. | `@Arguments Map` | For access to the raw map of arguments. @@ -160,27 +160,27 @@ See <>. | `@ProjectedPayload` Interface | For access to field arguments through a project interface. -See <>. +See xref:controllers.adoc#controllers.schema-mapping.projectedpayload.argument[`@ProjectedPayload` Interface]. | "Source" | For access to the source (i.e. parent/container) instance of the field. -See <>. +See xref:controllers.adoc#controllers.schema-mapping.source[Source]. | `Subrange` and `ScrollSubrange` | For access to pagination arguments. -See <>, <>, <>. +See xref:request-execution.adoc#execution.pagination[Pagination], xref:data.adoc#data.pagination.scroll[Scroll], xref:controllers.adoc#controllers.schema-mapping.subrange[`Subrange`]. | `Sort` | For access to sort details. -See <>, <>. +See xref:request-execution.adoc#execution.pagination[Pagination], xref:controllers.adoc#controllers.schema-mapping.sort[`Sort`]. | `DataLoader` | For access to a `DataLoader` in the `DataLoaderRegistry`. -See <>. +See xref:controllers.adoc#controllers.schema-mapping.data-loader[`DataLoader`]. | `@ContextValue` | For access to an attribute from the main `GraphQLContext` in `DataFetchingEnvironment`. @@ -212,7 +212,7 @@ 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 xref:request-execution.adoc#execution.reactive-datafetcher[Reactive `DataFetcher`]. - `java.util.concurrent.Callable` to have the value(s) produced asynchronously. For this to work, `AnnotatedControllerConfigurer` must be configured with an `Executor`. @@ -282,7 +282,7 @@ NOTE: Prior to 1.2, `@Argument Map` returned the full arguments the annotation did not specify a name. After 1.2, `@Argument` with `Map` always returns the raw argument value, matching either to the name specified in the annotation, or to the parameter name. For access to the full arguments -map, please use <> instead. +map, please use xref:controllers.adoc#controllers.schema-mapping.arguments[`@Arguments`] instead. [[controllers.schema-mapping.argument-value]] @@ -291,7 +291,7 @@ map, please use <> instead. 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 xref:controllers.adoc#controllers.schema-mapping.argument[`@Argument`] there is no way to make such a distinction, because you would get `null` or an empty `Optional` in both cases. @@ -340,7 +340,7 @@ all argument values. [[controllers.schema-mapping.projectedpayload.argument]] === `@ProjectedPayload` Interface -As an alternative to using complete Objects with <>, +As an alternative to using complete Objects with xref:controllers.adoc#controllers.schema-mapping.argument[`@Argument`], 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] @@ -413,7 +413,7 @@ explicitly specify the type name in the `@SchemaMapping` annotation. [TIP] ==== -A <> handler method can batch load all authors for a query, +A xref:controllers.adoc#controllers.batch-mapping[`@BatchMapping`] handler method can batch load all authors for a query, given a list of source/parent books objects. ==== @@ -421,7 +421,7 @@ given a list of source/parent books objects. [[controllers.schema-mapping.subrange]] === `Subrange` -When there is a <> bean in Spring configuration, +When there is a xref:request-execution.adoc#execution.pagination.cursor.strategy[`CursorStrategy`] bean in Spring configuration, controller methods support a `Subrange

` argument where `

` is a relative position converted from a cursor. For Spring Data, `ScrollSubrange` exposes `ScrollPosition`. For example: @@ -441,13 +441,13 @@ public class BookController { } ---- -See <> for an overview of pagination and of built-in mechanisms. +See xref:request-execution.adoc#execution.pagination[Pagination] for an overview of pagination and of built-in mechanisms. [[controllers.schema-mapping.sort]] === `Sort` -When there is a <> bean in Spring configuration, controller +When there is a xref:data.adoc#data.pagination.scroll[SortStrategy] bean in Spring configuration, controller methods support `Sort` as a method argument. For example: [source,java,indent=0,subs="verbatim,quotes"] @@ -469,7 +469,7 @@ public class BookController { === `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 +xref:request-execution.adoc#execution.batching[Batch Loading], 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"] @@ -500,7 +500,7 @@ 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. +xref:controllers.adoc#controllers.batch-mapping[@BatchMapping] method as described in the next section. [[controllers.schema-mapping.validation]] @@ -541,15 +541,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 xref:request-execution.adoc#execution.exceptions[Exceptions] 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 xref:controllers.adoc#controllers.schema-mapping.argument[`@Argument`], +xref:controllers.adoc#controllers.schema-mapping.arguments[`@Arguments`], and +xref:controllers.adoc#controllers.schema-mapping.projectedpayload.argument[@ProjectedPayload] method parameters, but applies more generally to any method parameter. [WARNING] @@ -566,7 +566,7 @@ for links to relevant issues and a suggested workaround. [[controllers.batch-mapping]] == `@BatchMapping` -<> addresses the N+1 select problem through the use of an +xref:request-execution.adoc#execution.batching[Batch Loading] 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: @@ -679,7 +679,7 @@ Batch mapping methods can return: == `@GraphQlExceptionHandler` Use `@GraphQlExceptionHandler` methods to handle exceptions from data fetching with a -flexible <>. When declared in a +flexible xref:controllers.adoc#controllers.exception-handler.signature[method signature]. When declared in a controller, exception handler methods apply to exceptions from the same controller: [source,java,indent=0,subs="verbatim,quotes"] @@ -719,7 +719,7 @@ Exception handling via `@GraphQlExceptionHandler` methods is applied automatical controller invocations. To handle exceptions from other `graphql.schema.DataFetcher` implementations, not based on controller methods, obtain a `DataFetcherExceptionResolver` from `AnnotatedControllerConfigurer`, and register it in -`GraphQlSource.Builder` as a <>. +`GraphQlSource.Builder` as a xref:request-execution.adoc#execution.exceptions[DataFetcherExceptionResolver]. @@ -729,7 +729,7 @@ implementations, not based on controller methods, obtain a Exception handler methods support a flexible method signature with method arguments resolved from a `DataFetchingEnvironment,` and matching to those of -<>. +xref:controllers.adoc#controllers.schema-mapping.arguments[@SchemaMapping methods]. Supported return types are listed below: @@ -753,4 +753,4 @@ Supported return types are listed below: | `Mono` | For asynchronous resolution where `` is one of the supported, synchronous, return types. -|=== \ No newline at end of file +|=== diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/data.adoc b/spring-graphql-docs/modules/ROOT/pages/data.adoc similarity index 90% rename from spring-graphql-docs/src/docs/asciidoc/includes/data.adoc rename to spring-graphql-docs/modules/ROOT/pages/data.adoc index 6114e37a3..b160d4b50 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/data.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/data.adoc @@ -47,7 +47,7 @@ Then use it to create a `DataFetcher`: ---- You can now register the above `DataFetcher` through a -<>. +xref:request-execution.adoc#execution.graphqlsource.runtimewiring-configurer[`RuntimeWiringConfigurer`]. The `DataFetcher` builds a Querydsl `Predicate` from GraphQL arguments, and uses it to fetch data. Spring Data supports `QuerydslPredicateExecutor` for JPA, MongoDB, Neo4j, and LDAP. @@ -68,8 +68,11 @@ https://querydsl.com/static/querydsl/latest/reference/html/ch02.html[official re For example: +[tabs] +====== +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,quotes,attributes",role="primary"] -.Gradle ---- dependencies { //... @@ -83,8 +86,10 @@ compileJava { options.annotationProcessorPath = configurations.annotationProcessor } ---- + +Maven:: ++ [source,xml,indent=0,subs="verbatim,quotes,attributes",role="secondary"] -.Maven ---- @@ -126,6 +131,7 @@ compileJava { ---- +====== The {github-10x-branch}/samples/webmvc-http[webmvc-http] sample uses Querydsl for `artifactRepositories`. @@ -140,7 +146,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 xref:data.adoc#data.querydsl.registration[Auto-Registration]. 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 @@ -148,7 +154,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 xref:data.adoc#data.projections[Selection Set vs Projections]. 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 @@ -187,7 +193,7 @@ or a target DTO class and configure it through the `projectAs` method to obtain If a repository is annotated with `@GraphQlRepository`, it is automatically registered for queries that do not already have a registered `DataFetcher` and whose return type matches that of the repository domain type. This includes single value queries, multi-value -queries, and <> queries. +queries, and xref:request-execution.adoc#execution.pagination[paginated] queries. By default, the name of the GraphQL type returned by the query must match the simple name of the repository domain type. If needed, you can use the `typeName` attribute of @@ -202,11 +208,11 @@ Auto-registration detects if a given repository implements `QuerydslBinderCustom transparently applies that through `QuerydslDataFetcher` builder methods. Auto-registration is performed through a built-in `RuntimeWiringConfigurer` that can be -obtained from `QuerydslDataFetcher`. The <> automatically +obtained from `QuerydslDataFetcher`. The xref:boot-starter.adoc[Boot Starter] automatically detects `@GraphQlRepository` beans and uses them to initialize the `RuntimeWiringConfigurer` with. -Auto-registration applies <> +Auto-registration applies xref:data.adoc#data.querybyexample.customizations[customizations] by calling `customize(Builder)` on the repository instance if your repository implements `QuerydslBuilderCustomizer` or `ReactiveQuerydslBuilderCustomizer` respectively. @@ -247,7 +253,7 @@ Use `QueryByExampleDataFetcher` to turn the repository into a `DataFetcher`: ---- You can now register the above `DataFetcher` through a -<>. +xref:request-execution.adoc#execution.graphqlsource.runtimewiring-configurer[`RuntimeWiringConfigurer`]. 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 @@ -276,7 +282,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 xref:data.adoc#data.projections[Selection Set vs Projections]. 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 @@ -314,7 +320,7 @@ or a target DTO class and configure it through the `projectAs` method to obtain If a repository is annotated with `@GraphQlRepository`, it is automatically registered for queries that do not already have a registered `DataFetcher` and whose return type matches that of the repository domain type. This includes single value queries, multi-value -queries, and <> queries. +queries, and xref:request-execution.adoc#execution.pagination[paginated] queries. By default, the name of the GraphQL type returned by the query must match the simple name of the repository domain type. If needed, you can use the `typeName` attribute of @@ -326,11 +332,11 @@ For paginated queries, the simple name of the repository domain type must match per page. Auto-registration is performed through a built-in `RuntimeWiringConfigurer` that can be -obtained from `QueryByExampleDataFetcher`. The <> automatically +obtained from `QueryByExampleDataFetcher`. The xref:boot-starter.adoc[Boot Starter] automatically detects `@GraphQlRepository` beans and uses them to initialize the `RuntimeWiringConfigurer` with. -Auto-registration applies <> +Auto-registration applies xref:data.adoc#data.querybyexample.customizations[customizations] by calling `customize(Builder)` on the repository instance if your repository implements `QueryByExampleBuilderCustomizer` or `ReactiveQueryByExampleBuilderCustomizer` respectively. @@ -359,7 +365,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 +xref:data.adoc#data.querydsl[Querydsl] and the xref:data.adoc#data.querybyexample[Query by Example] integrations turn the GraphQL selection set into property path hints that the underlying Spring Data module uses to limit the selection. @@ -394,7 +400,7 @@ required fields (or columns) are part of the database query result. [[data.pagination.scroll]] == Scroll -As explained in <>, the GraphQL Cursor Connection spec defines a +As explained in xref:request-execution.adoc#execution.pagination[Pagination], the GraphQL Cursor Connection spec defines a mechanism for pagination with `Connection`, `Edge`, and `PageInfo` schema types, while GraphQL Java provides the equivalent Java type representations. @@ -423,11 +429,11 @@ GraphQlSource.schemaResourceBuilder() <3> Register the type visitor. On the request side, a controller method can declare a -<> method argument to paginate forward -or backward. For this to work, you must declare a <> +xref:controllers.adoc#controllers.schema-mapping.subrange[ScrollSubrange] method argument to paginate forward +or backward. For this to work, you must declare a xref:request-execution.adoc#execution.pagination.cursor.strategy[`CursorStrategy`] supports `ScrollPosition` as a bean. -The <> declares a `CursorStrategy` bean, and registers the +The xref:boot-starter.adoc[Boot Starter] declares a `CursorStrategy` bean, and registers the `ConnectionFieldTypeVisitor` as shown above if Spring Data is on the classpath. @@ -479,4 +485,4 @@ Jackson library is on the classpath, customizations like the above are applied f Spring for GraphQL defines a `SortStrategy` to create `Sort` from GraphQL arguments. `AbstractSortStrategy` implements the contract with abstract methods to extract the sort direction and properties. To enable support for `Sort` as a controller method argument, -you need to declare a `SortStrategy` bean. \ No newline at end of file +you need to declare a `SortStrategy` bean. diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/graalvm-native.adoc b/spring-graphql-docs/modules/ROOT/pages/graalvm-native.adoc similarity index 98% rename from spring-graphql-docs/src/docs/asciidoc/includes/graalvm-native.adoc rename to spring-graphql-docs/modules/ROOT/pages/graalvm-native.adoc index b616b7a57..bfea87190 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/graalvm-native.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/graalvm-native.adoc @@ -37,7 +37,7 @@ This is all done automatically for you if you are building a Spring Boot applica If your application is "manually" registering data fetchers, some types are not discoverable as a result. You should then register them with Spring Framework's `@RegisterReflectionForBinding`: -include::code:GraphQlConfiguration[] +include-code::GraphQlConfiguration[] <1> This application declares a `RuntimeWiringConfigurer` that "manually" adds a `DataFetcher` <2> Through this `DataFetcher`, the `BookRepository` will expose a `Book` type <3> `@RegisterReflectionForBinding` will register the relevant hints for the `Book` type and all types exposed as fields @@ -50,7 +50,7 @@ The `AotProcessor` strategy described in the section above cannot be used as a r For client support, Spring for GraphQL embeds the {github-main-branch}/spring-graphql/src/main/resources/META-INF/native-image/org.springframework.graphql/spring-graphql[relevant reachability metadata for the client infrastructure]. When it comes to Java types used by the application, applications should use a similar strategy as "manual" data fetchers using `@RegisterReflectionForBinding`: -include::code:ProjectService[] +include-code::ProjectService[] <1> In a Native image, we need to ensure that reflection can be performed on `Project` at runtime <2> `@RegisterReflectionForBinding` will register the relevant hints for the `Project` type and all types exposed as fields diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/graphiql.adoc b/spring-graphql-docs/modules/ROOT/pages/graphiql.adoc similarity index 97% rename from spring-graphql-docs/src/docs/asciidoc/includes/graphiql.adoc rename to spring-graphql-docs/modules/ROOT/pages/graphiql.adoc index c77f39d01..ffaaa206e 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/graphiql.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/graphiql.adoc @@ -29,10 +29,10 @@ Alternatively, you can integrate the JavaScript build in your project as a separ Once a GraphiQL build is available on the classpath, you can expose it as an endpoint with the {spring-framework-ref-docs}/web/webmvc-functional.html#webmvc-fn-router-functions[functional web frameworks]. -include::code:GraphiQlConfiguration[] +include-code::GraphiQlConfiguration[] <1> Load the GraphiQL page from the classpath (here, we are using the version shipped with Spring for GraphQL) <2> Configure a web handler for processing HTTP requests; you can implement a custom `HandlerFunction` depending on your use case <3> Finally, map the handler to a specific HTTP endpoint <4> Expose this new route through a `RouterFunction` bean -You might also need to configure your application to {spring-boot-ref-docs}/web.html#web.servlet.spring-mvc.static-content[serve the relevant static resources]. \ No newline at end of file +You might also need to configure your application to {spring-boot-ref-docs}/web.html#web.servlet.spring-mvc.static-content[serve the relevant static resources]. diff --git a/spring-graphql-docs/modules/ROOT/pages/index.adoc b/spring-graphql-docs/modules/ROOT/pages/index.adoc new file mode 100644 index 000000000..56d438a56 --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/pages/index.adoc @@ -0,0 +1,18 @@ +[[overview]] += Spring for GraphQL + +Spring for GraphQL provides support for Spring applications built on +https://www.graphql-java.com/[GraphQL Java]. It is a joint collaboration between the +GraphQL Java team and Spring engineering. + +Spring for GraphQL is the successor of the +https://github.com/graphql-java/graphql-java-spring[GraphQL Java Spring] project from +the GraphQL Java team. It aims to be the foundation for all Spring, GraphQL applications. + +Please, use our https://github.com/spring-projects/spring-graphql/issues[issue tracker] +to report a problem, discuss a design issue, or to request a feature. + +Check the https://github.com/spring-projects/spring-graphql/wiki[Wiki]. +for what's new, baseline requirements, and upgrade notes, and other cross-version information. + +To get started, see the xref:boot-starter.adoc[Boot Starter] and xref:samples.adoc[Samples] sections. \ No newline at end of file diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/observability.adoc b/spring-graphql-docs/modules/ROOT/pages/observability.adoc similarity index 100% rename from spring-graphql-docs/src/docs/asciidoc/includes/observability.adoc rename to spring-graphql-docs/modules/ROOT/pages/observability.adoc diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/request-execution.adoc b/spring-graphql-docs/modules/ROOT/pages/request-execution.adoc similarity index 84% rename from spring-graphql-docs/src/docs/asciidoc/includes/request-execution.adoc rename to spring-graphql-docs/modules/ROOT/pages/request-execution.adoc index 75acafab0..42643ffce 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/request-execution.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/request-execution.adoc @@ -2,7 +2,7 @@ = 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 xref:transports.adoc#server.transports.http[HTTP], delegate to `ExecutionGraphQlService` to handle requests. The main implementation, `DefaultExecutionGraphQlService`, is configured with a @@ -17,15 +17,15 @@ The main implementation, `DefaultExecutionGraphQlService`, is configured with a includes a builder API to build that instance. The default builder is available via `GraphQlSource.schemaResourceBuilder()`. -The <> creates an instance of this builder and further initializes it -to <> from a configurable location, +The xref:boot-starter.adoc[Boot Starter] creates an instance of this builder and further initializes it +to xref:request-execution.adoc#execution.graphqlsource.schema-resources[load schema files] from a configurable location, to {spring-boot-ref-docs}/application-properties.html#appendix.application-properties.web[expose properties] to apply to `GraphQlSource.Builder`, to detect -<> beans, +xref:request-execution.adoc#execution.graphqlsource.runtimewiring-configurer[`RuntimeWiringConfigurer`] beans, https://www.graphql-java.com/documentation/instrumentation[Instrumentation] beans for {spring-boot-ref-docs}/actuator.html#actuator.metrics.supported.spring-graphql[GraphQL metrics], and `DataFetcherExceptionResolver` and `SubscriptionExceptionResolver` beans for -<>. For further customizations, you can also +xref:request-execution.adoc#execution.exceptions[exception resolution]. For further customizations, you can also declare a `GraphQlSourceBuilderCustomizer` bean, for example: [source,java,indent=0,subs="verbatim,quotes"] @@ -80,7 +80,7 @@ builder.schemaResources(..) }) ---- -The <> explains how to configure that with Spring Boot. +The xref:request-execution.adoc#execution.graphqlsource[GraphQlSource section] explains how to configure that with Spring Boot. For an example with Apollo Federation, see https://github.com/apollographql/federation-jvm-spring-example[federation-jvm-spring-example]. @@ -92,11 +92,11 @@ https://github.com/apollographql/federation-jvm-spring-example[federation-jvm-sp You can use `RuntimeWiringConfigurer` to register: - Custom scalar types. -- <> handling code. -- Default <> for interface and union types. -- `DataFetcher` for a field although applications will typically use <>, and +- xref:request-execution.adoc#execution.graphqlsource.directives[Directives] handling code. +- Default xref:request-execution.adoc#execution.graphqlsource.default-type-resolver[`TypeResolver`] for interface and union types. +- `DataFetcher` for a field although applications will typically use xref:controllers.adoc[Annotated Controllers], and those are detected and registered as ``DataFetcher``s by `AnnotatedControllerConfigurer`, -which is a `RuntimeWiringConfigurer`. The <> automatically registers +which is a `RuntimeWiringConfigurer`. The xref:boot-starter.adoc[Boot Starter] automatically registers `AnnotatedControllerConfigurer`. NOTE: GraphQL Java, server applications use Jackson only for serialization to and from maps of data. @@ -104,7 +104,7 @@ Client input is parsed into a map. Server output is assembled into a map based o This means you can't rely on Jackson serialization/deserialization annotations. Instead, you can use https://www.graphql-java.com/documentation/scalars/[custom scalar types]. -The <> detects beans of type `RuntimeWiringConfigurer` and +The xref:boot-starter.adoc[Boot Starter] detects beans of type `RuntimeWiringConfigurer` and registers them in the `GraphQlSource.Builder`. That means in most cases, you'll' have something like the following in your configuration: @@ -139,7 +139,7 @@ number of factories that are then invoked in sequence. `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 xref:request-execution.adoc#execution.graphqlsource.runtimewiring-configurer[`RuntimeWiringConfigurer`]. 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. @@ -159,7 +159,7 @@ classNameTypeResolver.setClassNameExtractor((klass) -> { builder.defaultTypeResolver(classNameTypeResolver); ---- -The <> explains how to configure that with Spring Boot. +The xref:request-execution.adoc#execution.graphqlsource[GraphQlSource section] explains how to configure that with Spring Boot. [[execution.graphqlsource.directives]] @@ -175,7 +175,7 @@ and handle directives. For more details, see GraphQL Java documentation. In Spring GraphQL you can register a `SchemaDirectiveWiring` through a -<>. The <> detects +xref:request-execution.adoc#execution.graphqlsource.runtimewiring-configurer[`RuntimeWiringConfigurer`]. The xref:boot-starter.adoc[Boot Starter] detects such beans, so you might have something like: [source,java,indent=0,subs="verbatim,quotes"] @@ -202,7 +202,7 @@ library. 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 xref:request-execution.adoc#execution.graphqlsource.schema-traversal[Schema Traversal] so generally prefer traversal to transformation unless you need to make schema changes. @@ -213,7 +213,7 @@ 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. +xref:request-execution.adoc#execution.graphqlsource.schema-transformation[Schema Transformation], if you need to make changes to the schema. [[execution.graphqlsource.schema-mapping-inspection]] @@ -234,8 +234,8 @@ structure. Spring for GraphQL defines the `SelfDescribingDataFetcher` interface to allow a `DataFetcher` to expose return type information. All Spring `DataFetcher` implementations -implement this interface. That includes those for <>, and those for -<> and <> Spring Data repositories. For annotated +implement this interface. That includes those for xref:controllers.adoc[Annotated Controllers], and those for +xref:data.adoc#data.querydsl[Querydsl] and xref:data.adoc#data.querybyexample[Query by Example] Spring Data repositories. For annotated controllers, the return type is derived from the declared return type on a `@SchemaMapping` method. @@ -315,7 +315,7 @@ builder.schemaResources(..) .configureGraphQl(graphQLBuilder -> graphQLBuilder.preparsedDocumentProvider(provider)) ---- -The <> explains how to configure that with Spring Boot. +The xref:request-execution.adoc#execution.graphqlsource[GraphQlSource section] explains how to configure that with Spring Boot. @@ -330,7 +330,7 @@ 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 -<>. +xref:request-execution.adoc#execution.context.webflux[WebFlux Context]. @@ -338,7 +338,7 @@ transport layer, such as from a WebFlux request handling, see == Context Propagation Spring for GraphQL provides support to transparently propagate context from the -<>, through GraphQL Java, and to `DataFetcher` and other components it +xref:transports.adoc#server.transports.http[HTTP], 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. @@ -348,7 +348,7 @@ thread and Reactor `Context` from the WebFlux processing pipeline. 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 +xref:transports.adoc#server.interception[`WebGraphQlInterceptor`] or `DataFetcher` switches to a different thread. Spring for GraphQL supports propagating `ThreadLocal` values from the Servlet container @@ -392,9 +392,9 @@ automatically through the `java.util.ServiceLoader` mechanism. [[execution.context.webflux]] === WebFlux -A <> can rely on access to Reactor context that +A xref:request-execution.adoc#execution.reactive-datafetcher[Reactive `DataFetcher`] can rely on access to Reactor context that originates from the WebFlux request handling chain. This includes Reactor context -added by <> components. +added by xref:transports.adoc#server.interception[WebGraphQlInterceptor] components. @@ -407,16 +407,16 @@ single handler only. Spring for GraphQL registers a `DataFetcherExceptionHandler` that provides default handling and enables the `DataFetcherExceptionResolver` contract. An application can -register any number of resolvers via <> builder and those are in +register any number of resolvers via xref:request-execution.adoc#execution.graphqlsource[`GraphQLSource`] builder and those are in order until one them resolves the `Exception` to a `List`. The Spring Boot starter detects beans of this type. `DataFetcherExceptionResolverAdapter` is a convenient base class with protected methods `resolveToSingleError` and `resolveToMultipleErrors`. -The <> programming model enables handling data fetching exceptions with +The xref:controllers.adoc[Annotated Controllers] programming model enables handling data fetching exceptions with annotated exception handler methods with a flexible method signature, see -<> for details. +xref:controllers.adoc#controllers.exception-handler[`@GraphQlExceptionHandler`] for details. A `GraphQLError` can be assigned to a category based on the GraphQL Java `graphql.ErrorClassification`, or the Spring GraphQL `ErrorType`, which defines the following: @@ -448,7 +448,7 @@ 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 xref:transports.adoc#server.interception.web[`WebGraphQlInterceptor`]. [[execution.exceptions.subscription]] @@ -537,13 +537,13 @@ and the following type definitions will be transparently added to the schema: } ---- -The <> registers `ConnectionTypeDefinitionConfigurer` by default. +The xref:boot-starter.adoc[Boot Starter] registers `ConnectionTypeDefinitionConfigurer` by default. [[execution.pagination.adapters]] === `ConnectionAdapter` -Once <> are available in the schema, you also need +Once xref:request-execution.adoc#execution.pagination.types[Connection Types] are available in the schema, you also need equivalent Java types. GraphQL Java provides those, including generic `Connection` and `Edge`, as well as a `PageInfo`. @@ -571,11 +571,11 @@ GraphQlSource.schemaResourceBuilder() <1> Create type visitor with one or more ``ConnectionAdapter``s. <2> Resister the type visitor. -There are <> ``ConnectionAdapter``s for Spring Data's +There are xref:data.adoc#data.pagination.scroll[built-in] ``ConnectionAdapter``s for Spring Data's `Window` and `Slice`. You can also create your own custom adapter. `ConnectionAdapter` -implementations rely on a <> to +implementations rely on a xref:request-execution.adoc#execution.pagination.cursor.strategy[`CursorStrategy`] to create cursors for returned items. The same strategy is also used to support the -<> controller method argument that contains +xref:controllers.adoc#controllers.schema-mapping.subrange[`Subrange`] controller method argument that contains pagination input. @@ -586,16 +586,16 @@ pagination input. position of an item within a large result set. The cursor can be based on an index or on a keyset. -A <> uses this to encode cursors for returned items. -<> methods, <> repositories, and <> +A xref:request-execution.adoc#execution.pagination.adapters[`ConnectionAdapter`] uses this to encode cursors for returned items. +xref:controllers.adoc[Annotated Controllers] methods, xref:data.adoc#data.querydsl[Querydsl] repositories, and xref:data.adoc#data.querybyexample[Query by Example] repositories use it to decode cursors from pagination requests, and create a `Subrange`. `CursorEncoder` is a related contract that further encodes and decodes String cursors to make them opaque to clients. `EncodingCursorStrategy` combines `CursorStrategy` with a `CursorEncoder`. You can use `Base64CursorEncoder`, `NoOpEncoder` or create your own. -There is a <> `CursorStrategy` for the Spring Data -`ScrollPosition`. The <> registers a `CursorStrategy` with +There is a xref:data.adoc#data.pagination.scroll[built-in] `CursorStrategy` for the Spring Data +`ScrollPosition`. The xref:boot-starter.adoc[Boot Starter] registers a `CursorStrategy` with `Base64Encoder` when Spring Data is present. @@ -606,7 +606,7 @@ There is no standard way to provide sort information in a GraphQL request. Howev pagination depends on a stable sort order. You can use a default order, or otherwise expose input types and extract sort details from GraphQL arguments. -There is <> support for Spring Data's `Sort` as a controller +There is xref:data.adoc#data.pagination.sort[built-in] support for Spring Data's `Sort` as a controller method argument. For this to work, you need to have a `SortStrategy` bean. @@ -663,14 +663,14 @@ public class MyConfig { } ---- -The <> declares a `BatchLoaderRegistry` bean that you can inject into +The xref:boot-starter.adoc[Boot Starter] declares a `BatchLoaderRegistry` bean that you can inject into your configuration, as shown above, or into any component such as a controller in order register batch loading functions. In turn the `BatchLoaderRegistry` is injected into `DefaultExecutionGraphQlService` where it ensures `DataLoader` registrations per request. 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 +xref:controllers.adoc#controllers.schema-mapping.data-loader[DataLoader argument] 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`. @@ -679,12 +679,12 @@ 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 +xref:controllers.adoc#controllers.batch-mapping[@BatchMapping] 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 xref:request-execution.adoc#execution.context[Context Propagation] 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. diff --git a/spring-graphql-docs/modules/ROOT/pages/samples.adoc b/spring-graphql-docs/modules/ROOT/pages/samples.adoc new file mode 100644 index 000000000..43b2327e4 --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/pages/samples.adoc @@ -0,0 +1,15 @@ +[[samples]] += Samples + +Check out the https://spring.io/guides/gs/graphql-server/["Building a GraphQL service"] Getting Started Guide. + +In addition, the 1.0.x branch of this repository contains {github-10x-branch}/samples[sample applications] for various scenarios. +Those samples do not exist in the `main` branch and are planned to be +https://github.com/spring-projects/spring-graphql/issues/208[moved out] into a separate repository. +To run those samples, check out the 1.0.x branch run their main application classes from your IDE, +or from the command line: + +[source,bash,indent=0,subs="verbatim,quotes"] +---- +$ ./gradlew :samples:{sample-directory-name}:bootRun +---- \ No newline at end of file diff --git a/spring-graphql-docs/modules/ROOT/pages/security.adoc b/spring-graphql-docs/modules/ROOT/pages/security.adoc new file mode 100644 index 000000000..d9321464c --- /dev/null +++ b/spring-graphql-docs/modules/ROOT/pages/security.adoc @@ -0,0 +1,23 @@ +[[security]] += Security + +The path to a xref:transports.adoc#server.transports.http[Web] 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 xref:request-execution.adoc#execution.context[Context Propagation] 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 +{github-10x-branch}/samples/webmvc-http-security[Spring MVC] and for +{github-10x-branch}/samples/webflux-security[WebFlux]. + + + + + + + diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/testing.adoc b/spring-graphql-docs/modules/ROOT/pages/testing.adoc similarity index 89% rename from spring-graphql-docs/src/docs/asciidoc/includes/testing.adoc rename to spring-graphql-docs/modules/ROOT/pages/testing.adoc index 949a4489d..7f5416174 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/testing.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/testing.adoc @@ -6,16 +6,21 @@ WebSocket, and RSocket, as well as for testing directly against a server. To make use of this, add `spring-graphql-test` to your build: +[tabs] +====== +Gradle:: ++ [source,groovy,indent=0,subs="verbatim,quotes,attributes",role="primary"] -.Gradle ---- dependencies { // ... testImplementation 'org.springframework.graphql:spring-graphql-test:{spring-graphql-version}' } ---- + +Maven:: ++ [source,xml,indent=0,subs="verbatim,quotes,attributes",role="secondary"] -.Maven ---- @@ -27,6 +32,7 @@ dependencies { ---- +====== @@ -42,17 +48,17 @@ specific is configured at build time. To create a `GraphQlTester` that performs requests through a client, you need one of the following extensions: -- <> -- <> -- <> +- xref:testing.adoc#testing.httpgraphqltester[HttpGraphQlTester] +- xref:testing.adoc#testing.websocketgraphqltester[WebSocketGraphQlTester] +- xref:testing.adoc#testing.rsocketgraphqltester[RSocketGraphQlTester] To create a `GraphQlTester` that performs tests on the server side, without a client: -- <> -- <> +- xref:testing.adoc#testing.graphqlservicetester[ExecutionGraphQlServiceTester] +- xref:testing.adoc#testing.webgraphqltester[WebGraphQlServiceTester] Each defines a `Builder` with options relevant to the transport. All builders extend -from a common, base GraphQlTester <> with +from a common, base GraphQlTester xref:testing.adoc#testing.graphqltester.builder[`Builder`] with options relevant to all extensions. @@ -109,7 +115,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 +xref:testing.adoc#testing.requests[execute requests] 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: @@ -152,7 +158,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 +xref:testing.adoc#testing.requests[execute requests] 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: @@ -202,7 +208,7 @@ 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 +xref:testing.adoc#testing.requests[execute requests] using the same API, independent of the underlying transport. @@ -220,7 +226,7 @@ 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 +xref:testing.adoc#testing.requests[execute requests] using the same API, independent of the underlying transport. `ExecutionGraphQlServiceTester.Builder` provides an option to customize `ExecutionInput` details: @@ -238,7 +244,7 @@ transport. [[testing.webgraphqltester]] === `WebGraphQlHandler` -The <> extension lets you test on the server side, without +The xref:testing.adoc#testing.graphqlservicetester[`GraphQlService`] 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. @@ -264,7 +270,7 @@ 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 +xref:testing.adoc#testing.requests[execute requests] using the same API, independent of the underlying transport. @@ -355,7 +361,7 @@ instead of `execute` to verify there are no errors in the response: graphQlTester.query(query).executeAndVerify(); ---- -See <> for more details on error handling. +See xref:testing.adoc#testing.errors[Errors] for more details on error handling. @@ -399,9 +405,9 @@ 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. +Subscriptions are supported only with xref:testing.adoc#testing.websocketgraphqltester[WebSocketGraphQlTester] +, or with the server side +xref:testing.adoc#testing.graphqlservicetester[`GraphQlService`] and xref:testing.adoc#testing.webgraphqltester[`WebGraphQlHandler`] extensions. diff --git a/spring-graphql-docs/src/docs/asciidoc/includes/transports.adoc b/spring-graphql-docs/modules/ROOT/pages/transports.adoc similarity index 88% rename from spring-graphql-docs/src/docs/asciidoc/includes/transports.adoc rename to spring-graphql-docs/modules/ROOT/pages/transports.adoc index 6fabee9fe..a79f77821 100644 --- a/spring-graphql-docs/src/docs/asciidoc/includes/transports.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/transports.adoc @@ -9,7 +9,7 @@ RSocket. == HTTP `GraphQlHttpHandler` handles GraphQL over HTTP requests and delegates to the -<> chain for request execution. There are two variants, one for +xref:transports.adoc#server.interception[Interception] 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. @@ -24,7 +24,7 @@ is also supported, as described in the specification. `GraphQlHttpHandler` can be exposed as an HTTP endpoint by declaring a `RouterFunction` bean and using the `RouterFunctions` from Spring MVC or WebFlux to create the route. The -<> does this, see the +xref:boot-starter.adoc[Boot Starter] does this, see the {spring-boot-ref-docs}/web.html#web.graphql.transports.http-websocket[Web Endpoints] section for details, or check `GraphQlWebMvcAutoConfiguration` or `GraphQlWebFluxAutoConfiguration` it contains, for the actual config. @@ -59,7 +59,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 xref:transports.adoc#server.interception[Interception] chain for further request execution. [TIP] @@ -84,7 +84,7 @@ https://github.com/enisdenjo/graphql-ws#recipes[recipes] for client use. `GraphQlWebSocketHandler` can be exposed as a WebSocket endpoint by declaring a `SimpleUrlHandlerMapping` bean and using it to map the handler to a URL path. By default, -the <> does not expose a GraphQL over WebSocket endpoint, but it's easy to +the xref:boot-starter.adoc[Boot Starter] does not expose a GraphQL over WebSocket endpoint, but it's easy to enable it by adding a property for the endpoint path. Please, see the {spring-boot-ref-docs}/web.html#web.graphql.transports.http-websocket[Web Endpoints] section for details, or check the `GraphQlWebMvcAutoConfiguration` or the @@ -105,7 +105,7 @@ handled as `request-stream`. `GraphQlRSocketHandler` can be used a delegate from an `@Controller` that is mapped to the route for GraphQL requests. For example: -include::code:GraphQlRSocketController[] +include-code::GraphQlRSocketController[] @@ -120,7 +120,7 @@ called to process a request. [[server.interception.web]] === `WebGraphQlInterceptor` -<> and <> transports invoke a chain of +xref:transports.adoc#server.transports.http[HTTP] and xref:transports.adoc#server.transports.websocket[WebSocket] 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: @@ -132,13 +132,13 @@ incoming requests and do one of the following: For example, an interceptor can pass an HTTP request header to a `DataFetcher`: -include::code:RequestHeaderInterceptor[] +include-code::RequestHeaderInterceptor[] <1> Interceptor adds HTTP request header value into GraphQLContext <2> Data controller method accesses the value Reversely, an interceptor can access values added to the `GraphQLContext` by a controller: -include::code:ResponseHeaderInterceptor[] +include-code::ResponseHeaderInterceptor[] <1> Controller adds value to the `GraphQLContext` <2> Interceptor uses the value to add an HTTP response header @@ -146,19 +146,19 @@ include::code:ResponseHeaderInterceptor[] request validation errors that are raised before execution begins and which cannot be handled with a `DataFetcherExceptionResolver`: -include::code:RequestErrorInterceptor[] +include-code::RequestErrorInterceptor[] <1> Return the same if `ExecutionResult` has a "data" key with non-null value <2> Check and transform the GraphQL errors <3> Update the `ExecutionResult` with the modified errors Use `WebGraphQlHandler` to configure the `WebGraphQlInterceptor` chain. This is supported -by the <>, see +by the xref:boot-starter.adoc[Boot Starter], see {spring-boot-ref-docs}/web.html#web.graphql.transports.http-websocket[Web Endpoints]. [[server.interception.rsocket]] === `RSocketQlInterceptor` -Similar to <>, an `RSocketQlInterceptor` allows intercepting +Similar to xref:transports.adoc#server.interception.web[`WebGraphQlInterceptor`], 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`. \ No newline at end of file +this to customize the `graphql.ExecutionInput` and the `graphql.ExecutionResult`. diff --git a/spring-graphql-docs/src/docs/asciidoc/attributes.adoc b/spring-graphql-docs/src/docs/asciidoc/attributes.adoc deleted file mode 100644 index 82b5c502e..000000000 --- a/spring-graphql-docs/src/docs/asciidoc/attributes.adoc +++ /dev/null @@ -1,26 +0,0 @@ -:chomp: default headers packages -:docs-site: https://docs.spring.io -:idprefix: -:idseparator: - -:toc: left -:toclevels: 4 -:tabsize: 4 -:numbered: -:sectanchors: -:sectnums: -:hide-uri-scheme: -: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 -// version attributes from main build.gradle -:spring-framework-ref-docs: https://docs.spring.io/spring-framework/reference -: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/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc deleted file mode 100644 index 3d0a9a502..000000000 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ /dev/null @@ -1,120 +0,0 @@ -= Spring for GraphQL Documentation -Brian Clozel; Andreas Marek; Rossen Stoyanchev; Mark Paluch -include::attributes.adoc[] - - -[[overview]] -== Overview - -Spring for GraphQL provides support for Spring applications built on -https://www.graphql-java.com/[GraphQL Java]. It is a joint collaboration between the -GraphQL Java team and Spring engineering. - -Spring for GraphQL is the successor of the -https://github.com/graphql-java/graphql-java-spring[GraphQL Java Spring] project from -the GraphQL Java team. It aims to be the foundation for all Spring, GraphQL applications. - -Please, use our https://github.com/spring-projects/spring-graphql/issues[issue tracker] -to report a problem, discuss a design issue, or to request a feature. - -Check the https://github.com/spring-projects/spring-graphql/wiki[Wiki]. -for what's new, baseline requirements, and upgrade notes, and other cross-version information. - -To get started, see the <> and <> sections. - - - -include::includes/transports.adoc[leveloffset=+1] - - - -include::includes/request-execution.adoc[leveloffset=+1] - - - -include::includes/data.adoc[leveloffset=+1] - - - -include::includes/controllers.adoc[leveloffset=+1] - - - -[[security]] -== Security - -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 -Security, and other context, available at the data fetching level. - -The 1.0.x branch of this repository contains samples for -{github-10x-branch}/samples/webmvc-http-security[Spring MVC] and for -{github-10x-branch}/samples/webflux-security[WebFlux]. - - - -include::includes/observability.adoc[leveloffset=+1] - - - -include::includes/graalvm-native.adoc[leveloffset=+1] - - - -include::includes/client.adoc[leveloffset=+1] - - - -include::includes/graphiql.adoc[leveloffset=+1] - - - -include::includes/testing.adoc[leveloffset=+1] - - - -[[boot-starter]] -== Boot Starter - -Spring Boot provides a starter for building GraphQL applications with Spring for GraphQL. -For version information, see the -https://github.com/spring-projects/spring-graphql/wiki/Spring-for-GraphQL-Versions[Spring for GraphQL Versions] wiki page. - -The easiest way to get started is via https://start.spring.io by selecting -"Spring for GraphQL" along with an underlying transport such as Spring MVC of WebFlux over -HTTP or WebSocket, or over RSocket. Refer to the -https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.graphql[Spring for GraphQL Starter] -section in the Spring Boot reference for details on supported transports, auto-configuration related -features, and more. For testing support, see -https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.testing.spring-boot-applications.spring-graphql-tests[Auto-Configured GraphQL Tests]. - -For further reference, check the following GraphQL related: - -- https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.metrics.supported.spring-graphql[Metrics] -- https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties.web[Properties] -- https://docs.spring.io/spring-boot/docs/current/reference/html/auto-configuration-classes.html#appendix.auto-configuration-classes.core[Auto-Configuration Classes] - - - - -[[samples]] -== Samples - -Check out the https://spring.io/guides/gs/graphql-server/["Building a GraphQL service"] Getting Started Guide. - -In addition, the 1.0.x branch of this repository contains {github-10x-branch}/samples[sample applications] for various scenarios. -Those samples do not exist in the `main` branch and are planned to be -https://github.com/spring-projects/spring-graphql/issues/208[moved out] into a separate repository. -To run those samples, check out the 1.0.x branch run their main application classes from your IDE, -or from the command line: - -[source,bash,indent=0,subs="verbatim,quotes"] ----- -$ ./gradlew :samples:{sample-directory-name}:bootRun -----