Configure RSocket server support in GraphQL
This commit adds the RSocket server auto-configuration for GraphQL. See gh-30453
This commit is contained in:
@@ -41,6 +41,8 @@ public class GraphQlProperties {
|
||||
|
||||
private final Websocket websocket = new Websocket();
|
||||
|
||||
private final Rsocket rsocket = new Rsocket();
|
||||
|
||||
public Graphiql getGraphiql() {
|
||||
return this.graphiql;
|
||||
}
|
||||
@@ -61,6 +63,10 @@ public class GraphQlProperties {
|
||||
return this.websocket;
|
||||
}
|
||||
|
||||
public Rsocket getRsocket() {
|
||||
return this.rsocket;
|
||||
}
|
||||
|
||||
public static class Schema {
|
||||
|
||||
/**
|
||||
@@ -204,4 +210,21 @@ public class GraphQlProperties {
|
||||
|
||||
}
|
||||
|
||||
public static class Rsocket {
|
||||
|
||||
/**
|
||||
* Mapping of the RSocket message handler.
|
||||
*/
|
||||
private String mapping;
|
||||
|
||||
public String getMapping() {
|
||||
return this.mapping;
|
||||
}
|
||||
|
||||
public void setMapping(String mapping) {
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.graphql.rsocket;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import graphql.GraphQL;
|
||||
import io.rsocket.core.RSocketServer;
|
||||
import reactor.netty.http.server.HttpServer;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.graphql.ExecutionGraphQlService;
|
||||
import org.springframework.graphql.data.method.annotation.support.AnnotatedControllerConfigurer;
|
||||
import org.springframework.graphql.execution.GraphQlSource;
|
||||
import org.springframework.graphql.server.GraphQlRSocketHandler;
|
||||
import org.springframework.graphql.server.RSocketGraphQlInterceptor;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for enabling Spring GraphQL over
|
||||
* RSocket.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.7.0
|
||||
*/
|
||||
@AutoConfiguration(after = { GraphQlAutoConfiguration.class, RSocketMessagingAutoConfiguration.class })
|
||||
@ConditionalOnClass({ GraphQL.class, GraphQlSource.class, RSocketServer.class, HttpServer.class })
|
||||
@ConditionalOnBean({ RSocketMessageHandler.class, AnnotatedControllerConfigurer.class })
|
||||
@ConditionalOnProperty(prefix = "spring.graphql.rsocket", name = "mapping")
|
||||
public class GraphQlRSocketAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public GraphQlRSocketHandler graphQlRSocketHandler(ExecutionGraphQlService graphQlService,
|
||||
ObjectProvider<RSocketGraphQlInterceptor> interceptorsProvider, ObjectMapper objectMapper) {
|
||||
List<RSocketGraphQlInterceptor> interceptors = interceptorsProvider.orderedStream()
|
||||
.collect(Collectors.toList());
|
||||
return new GraphQlRSocketHandler(graphQlService, interceptors, new Jackson2JsonEncoder(objectMapper));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public GraphQlRSocketController graphQlRSocketController(GraphQlRSocketHandler handler) {
|
||||
return new GraphQlRSocketController(handler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.graphql.rsocket;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.server.GraphQlRSocketHandler;
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
||||
@Controller
|
||||
class GraphQlRSocketController {
|
||||
|
||||
private final GraphQlRSocketHandler handler;
|
||||
|
||||
GraphQlRSocketController(GraphQlRSocketHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@MessageMapping("${spring.graphql.rsocket.mapping}")
|
||||
Mono<Map<String, Object>> handle(Map<String, Object> payload) {
|
||||
return this.handler.handle(payload);
|
||||
}
|
||||
|
||||
@MessageMapping("${spring.graphql.rsocket.mapping}")
|
||||
Flux<Map<String, Object>> handleSubscription(Map<String, Object> payload) {
|
||||
return this.handler.handleSubscription(payload);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2020-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration classes for RSocket integration with GraphQL.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.graphql.rsocket;
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.graphql.rsocket;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import graphql.schema.idl.TypeRuntimeWiring;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.graphql.GraphQlTestDataFetchers;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
|
||||
import org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
|
||||
import org.springframework.boot.web.embedded.netty.NettyRouteProvider;
|
||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.graphql.client.RSocketGraphQlClient;
|
||||
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
|
||||
import org.springframework.graphql.server.GraphQlRSocketHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link GraphQlRSocketAutoConfiguration}
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class GraphQlRSocketAutoConfigurationTests {
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(JacksonAutoConfiguration.class, RSocketStrategiesAutoConfiguration.class,
|
||||
RSocketMessagingAutoConfiguration.class, RSocketServerAutoConfiguration.class,
|
||||
GraphQlAutoConfiguration.class, GraphQlRSocketAutoConfiguration.class))
|
||||
.withUserConfiguration(DataFetchersConfiguration.class)
|
||||
.withPropertyValues("spring.main.web-application-type=reactive", "spring.graphql.rsocket.mapping=graphql");
|
||||
|
||||
@Test
|
||||
void shouldContributeDefaultBeans() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(GraphQlRSocketHandler.class)
|
||||
.hasSingleBean(GraphQlRSocketController.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void simpleQueryShouldWorkWithTcpServer() {
|
||||
testWithRSocketTcp(this::assertThatSimpleQueryWorks);
|
||||
}
|
||||
|
||||
@Test
|
||||
void simpleQueryShouldWorkWithWebSocketServer() {
|
||||
testWithRSocketWebSocket(this::assertThatSimpleQueryWorks);
|
||||
}
|
||||
|
||||
private void assertThatSimpleQueryWorks(RSocketGraphQlClient client) {
|
||||
String document = "{ bookById(id: \"book-1\"){ id name pageCount author } }";
|
||||
String bookName = client.document(document).retrieve("bookById.name").toEntity(String.class)
|
||||
.block(Duration.ofSeconds(5));
|
||||
assertThat(bookName).isEqualTo("GraphQL for beginners");
|
||||
}
|
||||
|
||||
private void testWithRSocketTcp(Consumer<RSocketGraphQlClient> consumer) {
|
||||
ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(JacksonAutoConfiguration.class, RSocketStrategiesAutoConfiguration.class,
|
||||
RSocketMessagingAutoConfiguration.class, RSocketServerAutoConfiguration.class,
|
||||
GraphQlAutoConfiguration.class, GraphQlRSocketAutoConfiguration.class))
|
||||
.withUserConfiguration(DataFetchersConfiguration.class).withPropertyValues(
|
||||
"spring.main.web-application-type=reactive", "spring.graphql.rsocket.mapping=graphql");
|
||||
contextRunner.withInitializer(new RSocketPortInfoApplicationContextInitializer())
|
||||
.withPropertyValues("spring.rsocket.server.port=0").run((context) -> {
|
||||
String serverPort = context.getEnvironment().getProperty("local.rsocket.server.port");
|
||||
RSocketGraphQlClient client = RSocketGraphQlClient.builder()
|
||||
.tcp("localhost", Integer.parseInt(serverPort)).route("graphql").build();
|
||||
consumer.accept(client);
|
||||
});
|
||||
}
|
||||
|
||||
private void testWithRSocketWebSocket(Consumer<RSocketGraphQlClient> consumer) {
|
||||
ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
|
||||
AnnotationConfigReactiveWebServerApplicationContext::new).withConfiguration(
|
||||
AutoConfigurations.of(HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class,
|
||||
ErrorWebFluxAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class, RSocketStrategiesAutoConfiguration.class,
|
||||
RSocketMessagingAutoConfiguration.class, RSocketServerAutoConfiguration.class,
|
||||
GraphQlAutoConfiguration.class, GraphQlRSocketAutoConfiguration.class))
|
||||
.withInitializer(new ServerPortInfoApplicationContextInitializer())
|
||||
.withUserConfiguration(DataFetchersConfiguration.class, NettyServerConfiguration.class)
|
||||
.withPropertyValues("spring.main.web-application-type=reactive", "server.port=0",
|
||||
"spring.graphql.rsocket.mapping=graphql", "spring.rsocket.server.transport=websocket",
|
||||
"spring.rsocket.server.mapping-path=/rsocket");
|
||||
contextRunner.run((context) -> {
|
||||
String serverPort = context.getEnvironment().getProperty("local.server.port");
|
||||
RSocketGraphQlClient client = RSocketGraphQlClient.builder()
|
||||
.webSocket(URI.create("ws://localhost:" + serverPort + "/rsocket")).route("graphql").build();
|
||||
consumer.accept(client);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class NettyServerConfiguration {
|
||||
|
||||
@Bean
|
||||
NettyReactiveWebServerFactory serverFactory(NettyRouteProvider routeProvider) {
|
||||
NettyReactiveWebServerFactory serverFactory = new NettyReactiveWebServerFactory(0);
|
||||
serverFactory.addRouteProviders(routeProvider);
|
||||
return serverFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class DataFetchersConfiguration {
|
||||
|
||||
@Bean
|
||||
RuntimeWiringConfigurer bookDataFetcher() {
|
||||
return (builder) -> builder.type(TypeRuntimeWiring.newTypeWiring("Query").dataFetcher("bookById",
|
||||
GraphQlTestDataFetchers.getBookByIdDataFetcher()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
[[web.graphql]]
|
||||
== Spring GraphQL
|
||||
If you want to build GraphQL applications, you can take advantage of Spring Boot's auto-configuration for {spring-graphql}[Spring GraphQL].
|
||||
The Spring GraphQL project is based on https://github.com/graphql-java/graphql-java[GraphQL Java].
|
||||
== Spring for GraphQL
|
||||
If you want to build GraphQL applications, you can take advantage of Spring Boot's auto-configuration for {spring-graphql}[Spring for GraphQL].
|
||||
The Spring for GraphQL project is based on https://github.com/graphql-java/graphql-java[GraphQL Java].
|
||||
You'll need the `spring-boot-starter-graphql` starter at a minimum.
|
||||
Because GraphQL is transport-agnostic, you'll also need to have one or more additional starters in your application to expose your GraphQL API over the web:
|
||||
|
||||
@@ -22,6 +22,9 @@ Because GraphQL is transport-agnostic, you'll also need to have one or more addi
|
||||
| HTTP, WebSocket
|
||||
| Spring WebFlux
|
||||
|
||||
| `spring-boot-starter-rsocket`
|
||||
| TCP, WebSocket
|
||||
| Spring WebFlux on Reactor Netty
|
||||
|===
|
||||
|
||||
|
||||
@@ -74,9 +77,11 @@ Spring Data repositories annotated with `@GraphQlRepository` and extending one o
|
||||
are detected by Spring Boot and considered as candidates for `DataFetcher` for matching top-level queries.
|
||||
|
||||
|
||||
[[web.graphql.transports]]
|
||||
=== Transports
|
||||
|
||||
[[web.graphql.web-endpoints]]
|
||||
=== Web Endpoints
|
||||
[[web.graphql.transports.http-websocket]]
|
||||
==== HTTP and WebSocket
|
||||
|
||||
The GraphQL HTTP endpoint is at HTTP POST "/graphql" by default. The path can be customized with configprop:spring.graphql.path[].
|
||||
|
||||
@@ -91,10 +96,6 @@ This is quite useful for retrieving information from an HTTP request header and
|
||||
With Spring Boot, you can declare a `WebInterceptor` bean to have it registered with the web transport.
|
||||
|
||||
|
||||
|
||||
[[web.graphql.cors]]
|
||||
=== CORS
|
||||
|
||||
{spring-framework-docs}/web.html#mvc-cors[Spring MVC] and {spring-framework-docs}/web-reactive.html#webflux-cors[Spring WebFlux] support CORS (Cross-Origin Resource Sharing) requests.
|
||||
CORS is a critical part of the web config for GraphQL applications that are accessed from browsers using different domains.
|
||||
|
||||
@@ -111,6 +112,19 @@ Spring Boot supports many configuration properties under the `spring.graphql.cor
|
||||
----
|
||||
|
||||
|
||||
[[web.graphql.transports.rsocket]]
|
||||
==== RSocket
|
||||
|
||||
RSocket is also supported as a transport, on top of WebSocket or TCP.
|
||||
Once the <<messaging#messaging.rsocket.server-auto-configuration,RSocket server is configured>>, we can configure our GraphQL handler on a particular route using configprop:spring.graphql.rsocket.mapping[].
|
||||
For example, configuring that mapping as `"graphql"` means we can use the `RSocketGraphQlClient` as follows.
|
||||
|
||||
For RSocket over TCP:
|
||||
include::code:RSocketGraphQlClientExample[tag=tcp]
|
||||
|
||||
For RSocket over WebSocket:
|
||||
include::code:RSocketGraphQlClientExample[tag=websocket]
|
||||
|
||||
|
||||
[[web.graphql.exception-handling]]
|
||||
=== Exceptions Handling
|
||||
@@ -126,7 +140,7 @@ Spring Boot will automatically detect `DataFetcherExceptionResolver` beans and r
|
||||
|
||||
Spring GraphQL offers infrastructure for helping developers when consuming or developing a GraphQL API.
|
||||
|
||||
Spring GraphQL ships with a default https://github.com/graphql/graphiql[GraphiQL] page that is exposed at "/graphiql" by default.
|
||||
Spring GraphQL ships with a default https://github.com/graphql/graphiql[GraphiQL] page that is exposed at `"/graphiql"` by default.
|
||||
This page is disabled by default and can be turned on with the configprop:spring.graphql.graphiql.enabled[] property.
|
||||
Many applications exposing such a page will prefer a custom build.
|
||||
A default implementation is very useful during development, this is why it is exposed automatically with <<using#using.devtools,`spring-boot-devtools`>> during development.
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.docs.web.graphql.transports.rsocket;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.graphql.client.RSocketGraphQlClient;
|
||||
|
||||
public class RSocketGraphQlClientExample {
|
||||
|
||||
public void rsocketOverTcp() {
|
||||
// tag::tcp[]
|
||||
RSocketGraphQlClient client = RSocketGraphQlClient.builder().tcp("example.spring.io", 8181).route("graphql")
|
||||
.build();
|
||||
Mono<Book> book = client.document("{ bookById(id: \"book-1\"){ id name pageCount author } }")
|
||||
.retrieve("bookById").toEntity(Book.class);
|
||||
// end::tcp[]
|
||||
book.block(Duration.ofSeconds(5));
|
||||
}
|
||||
|
||||
public void rsocketOverWebSocket() {
|
||||
// tag::websocket[]
|
||||
RSocketGraphQlClient client = RSocketGraphQlClient.builder()
|
||||
.webSocket(URI.create("wss://example.spring.io/rsocket")).route("graphql").build();
|
||||
Mono<Book> book = client.document("{ bookById(id: \"book-1\"){ id name pageCount author } }")
|
||||
.retrieve("bookById").toEntity(Book.class);
|
||||
// end::websocket[]
|
||||
book.block(Duration.ofSeconds(5));
|
||||
}
|
||||
|
||||
static class Book {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.docs.web.graphql.transports.rsocket
|
||||
|
||||
import org.springframework.graphql.client.RSocketGraphQlClient
|
||||
import java.net.URI
|
||||
import java.time.Duration
|
||||
|
||||
|
||||
class RSocketGraphQlClientExample {
|
||||
|
||||
fun rsocketOverTcp() {
|
||||
// tag::tcp[]
|
||||
val client = RSocketGraphQlClient.builder()
|
||||
.tcp("example.spring.io", 8181)
|
||||
.route("graphql")
|
||||
.build()
|
||||
val book = client.document(
|
||||
"""
|
||||
{
|
||||
bookById(id: "book-1"){
|
||||
id
|
||||
name
|
||||
pageCount
|
||||
author
|
||||
}
|
||||
}
|
||||
""")
|
||||
.retrieve("bookById").toEntity(Book::class.java)
|
||||
// end::tcp[]
|
||||
book.block(Duration.ofSeconds(5))
|
||||
}
|
||||
|
||||
fun rsocketOverWebSocket() {
|
||||
// tag::websocket[]
|
||||
val client = RSocketGraphQlClient.builder()
|
||||
.webSocket(URI.create("wss://example.spring.io/rsocket"))
|
||||
.route("graphql")
|
||||
.build()
|
||||
val book = client.document(
|
||||
"""
|
||||
{
|
||||
bookById(id: "book-1"){
|
||||
id
|
||||
name
|
||||
pageCount
|
||||
author
|
||||
}
|
||||
}
|
||||
""")
|
||||
.retrieve("bookById").toEntity(Book::class.java)
|
||||
// end::websocket[]
|
||||
book.block(Duration.ofSeconds(5))
|
||||
}
|
||||
|
||||
internal class Book
|
||||
}
|
||||
Reference in New Issue
Block a user