From 681a0dcf4dbb2f063e033779b0b2a8f9499b74b8 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Mon, 28 Mar 2022 08:04:31 +0000 Subject: [PATCH] Update documentation for RSocket See gh-339 --- .../src/docs/asciidoc/client.adoc | 24 ++- .../src/docs/asciidoc/index.adoc | 137 +++++++++++------- 2 files changed, 109 insertions(+), 52 deletions(-) diff --git a/spring-graphql-docs/src/docs/asciidoc/client.adoc b/spring-graphql-docs/src/docs/asciidoc/client.adoc index aac06605..170ca46c 100644 --- a/spring-graphql-docs/src/docs/asciidoc/client.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/client.adoc @@ -6,8 +6,8 @@ include::attributes.adoc[] [[client]] = Client -Spring for GraphQL includes client support for executing GraphQL requests over HTTP or -over WebSocket. +Spring for GraphQL includes client support for executing GraphQL requests over HTTP, +WebSocket, and RSocket. @@ -108,6 +108,26 @@ on an existing `WebSocketGraphQlClient` to create another with different configu +[[client-rsocketgraphqlclient]] +=== RSocket + +`RSocketGraphQlClient` uses +{spring-framework-ref-docs}/web-reactive.html#rsocket-requester[RSocketRequester] +to execute GraphQL requests over RSocket requests. + +[source,java,indent=0,subs="verbatim,quotes"] +---- + RSocketGraphQlClient graphQlClient = + RSocketGraphQlClient.builder() + .websocket(URI.create("http://localhost:8080/graphql")) + .build(); +---- + +Once created, `RSocketGraphQlClient` exposes the same transport agnostic workflow for +request execution as any `GrahQlClient`. + + + [[client-websocketgraphqlclient-connection]] ==== Connection diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index 9ddd7b7b..a0f9492a 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -35,18 +35,18 @@ Spring for GraphQL requires the following as a baseline: -[[web-transports]] -== Web Transports +[[server-transports]] +== Server Transports -Spring for GraphQL supports GraphQL requests over HTTP and over WebSocket. +Spring for GraphQL supports server handling of GraphQL requests over HTTP, WebSocket, and +RSocket. - -[[web-http]] +[[server-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. @@ -70,7 +70,7 @@ The Spring for GraphQL repository contains a Spring MVC -[[web-websocket]] +[[server-websocket]] === WebSocket `GraphQlWebSocketHandler` handles GraphQL over WebSocket requests based on the @@ -78,7 +78,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] @@ -113,17 +113,52 @@ The Spring for GraphQL repository contains a WebFlux -[[web-interception]] -=== Web Interception +[[server-rsocket]] +=== RSocket -<> and <> transport handlers delegate to a common Web -interception chain for request execution. The chain consists of a sequence of -`WebGraphQlInterceptor` components, followed by a `ExecutionGraphQlService` that -invokes GraphQL Java. +`GraphQlRSocketHandler` handles GraphQL over RSocket requests. Queries and mutations are +expected and handled as an RSocket `request-response` interaction while subscriptions are +handled as `request-stream`. -`WebGraphQlInterceptor` is as a common contract to use in both Spring MVC and -WebFlux applications. Use it to intercept requests, inspect HTTP request headers, or to -register a transformation of the `graphql.ExecutionInput`: +`GraphQlRSocketHandler` can be used a delegate from an `@Controller` that is mapped to +the route for GraphQL requests. For example: + +[source,java,indent=0,subs="verbatim,quotes"] +---- +@Controller +public class GraphQlRSocketController { + + private final GraphQlRSocketHandler handler; + + GraphQlRSocketController(GraphQlRSocketHandler handler) { + this.handler = handler; + } + + @MessageMapping("graphql") + public Mono> handle(Map payload) { + return this.handler.handle(payload); + } + + @MessageMapping("graphql") + public Flux> handleSubscription(Map payload) { + return this.handler.handleSubscription(payload); + } +} +---- + + + + + +[[server-interception]] +=== Server Interception + +GraphQL <> and <> handlers for Spring MVC and WebFlux +delegate to a common `WebGraphQlInterceptor` chain followed by an `ExecutionGraphQlService` +that invokes the GraphQL Java engine. + +You can write an interceptor to check requests details or transform the +`graphql.ExecutionInput` for GraphQL Java: [source,java,indent=0,subs="verbatim,quotes"] ---- @@ -140,8 +175,8 @@ class MyInterceptor implements WebGraphQlInterceptor { } ---- -Use `WebGraphQlInterceptor` also to intercept responses, add HTTP response headers, -or transform the `graphql.ExecutionResult`: +Interceptors can customize HTTP response headers, or inspect and/or transform the +`graphql.ExecutionResult` from GraphQL Java: [source,java,indent=0,subs="verbatim,quotes"] ---- @@ -159,19 +194,22 @@ class MyInterceptor implements WebGraphQlInterceptor { } ---- -`WebGraphQlHandler` provides a builder to initialize the Web interception chain. After -you build the chain, you can use the resulting `WebGraphQlHandler` to initialize the HTTP -or WebSocket transport handlers. The Boot starter configures all this, see the -{spring-boot-ref-docs}/web.html#web.graphql.web-endpoints[Web Endpoints] section for -details, or check `GraphQlWebMvcAutoConfiguration` or `GraphQlWebFluxAutoConfiguration` -it contains, for the actual config. +`WebGraphQlHandler` has a builder to create the `WebGraphInterceptor` chain. The Boot +starter uses this, see Boot's section on +{spring-boot-ref-docs}/web.html#web.graphql.web-endpoints[Web Endpoints]. + +The <> handler delegates to a similar chain except +the interceptor type is `GraphQlInterceptor`. To use, create `GraphQlRSocketHandler` with +the list of interceptors to apply to requests. + + [[execution]] == 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 @@ -212,10 +250,9 @@ class GraphQlConfig { @Bean public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() { - return (builder) -> { - builder.configureGraphQl(graphQlBuilder -> - graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider())); - }; + return (builder) -> + builder.configureGraphQl(graphQlBuilder -> + graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider())); } } ---- @@ -380,10 +417,10 @@ such beans, so you might have something like: @Configuration public class GraphQlConfig { - @Bean - public RuntimeWiringConfigurer runtimeWiringConfigurer() { - return builder -> builder.directiveWiring(new MySchemaDirectiveWiring()); - } + @Bean + public RuntimeWiringConfigurer runtimeWiringConfigurer() { + return builder -> builder.directiveWiring(new MySchemaDirectiveWiring()); + } } ---- @@ -413,7 +450,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 +<>, 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. @@ -423,7 +460,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 +<> or `DataFetcher` switches to a different thread. Spring for GraphQL supports propagating `ThreadLocal` values from the Servlet container @@ -457,7 +494,7 @@ public class RequestAttributesAccessor implements ThreadLocalAccessor { } ---- -A `ThreadLocalAccessor` can be registered in the <> +A `ThreadLocalAccessor` can be registered in the <> builder. The Boot starter detects beans of this type and automatically registers them for Spring MVC application, see the {spring-boot-ref-docs}/web.html#web.graphql.web-endpoints[Web Endpoints] section. @@ -468,7 +505,7 @@ Spring MVC application, see the 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. @@ -546,11 +583,11 @@ public class MyConfig { public MyConfig(BatchLoaderRegistry registry) { registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> { - // return Mono - }); + // return Mono + }); - // more registrations ... - } + // more registrations ... + } } ---- @@ -679,12 +716,12 @@ dependencies { //... annotationProcessor "com.querydsl:querydsl-apt:$querydslVersion:jpa", - 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final', - 'javax.annotation:javax.annotation-api:1.3.2' + 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final', + 'javax.annotation:javax.annotation-api:1.3.2' } compileJava { - options.annotationProcessorPath = configurations.annotationProcessor + options.annotationProcessorPath = configurations.annotationProcessor } ---- [source,xml,indent=0,subs="verbatim,quotes,attributes",role="secondary"] @@ -1238,12 +1275,12 @@ Bean Validation lets you declare constraints on types, as the following example ---- public class BookInput { - @NotNull - private String title; + @NotNull + private String title; @NotNull - @Size(max=13) - private String isbn; + @Size(max=13) + private String isbn; } ---- @@ -1502,7 +1539,7 @@ 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.