diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java b/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java index 81d59394..1651dc40 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/GraphQlTransport.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.graphql.client; import graphql.ExecutionResult; @@ -21,8 +22,9 @@ import reactor.core.publisher.Mono; import org.springframework.graphql.GraphQlRequest; + /** - * Contract for a transport, over which to execute GraphQL requests. + * Contract for GraphQL request execution over some transport. * * @author Rossen Stoyanchev * @since 1.0.0 diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java b/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java index 6ffd963e..9f929446 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/HttpGraphQlTransport.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.graphql.client; import java.util.Map; @@ -33,24 +34,10 @@ import org.springframework.web.reactive.function.client.WebClient; * Supports only single-response requests over HTTP POST. For subscription * requests, see {@link WebSocketGraphQlTransport}. * - *

Use the builder to initialize the transport and the {@code GraphQlClient} - * in a single chain: - * - *

- * GraphQlClient client = HttpGraphQlTransport.builder(webClient).buildClient();
- * 
- * - *

Or build the transport and the client separately: - * - *

- * HttpGraphQlTransport transport = HttpGraphQlTransport.create(webClient);
- * GraphQlClient client = GraphQlClient.create(transport);
- * 
- * * @author Rossen Stoyanchev * @since 1.0.0 */ -public class HttpGraphQlTransport implements GraphQlTransport { +final class HttpGraphQlTransport implements GraphQlTransport { private static final ParameterizedTypeReference> MAP_TYPE = new ParameterizedTypeReference>() {}; @@ -59,20 +46,12 @@ public class HttpGraphQlTransport implements GraphQlTransport { private final WebClient webClient; - private HttpGraphQlTransport(WebClient webClient) { + HttpGraphQlTransport(WebClient webClient) { Assert.notNull(webClient, "WebClient is required"); this.webClient = webClient; } - /** - * Return the underlying {@code WebClient}. - */ - public WebClient getWebClient() { - return this.webClient; - } - - @Override public Mono execute(GraphQlRequest request) { return this.webClient.post() @@ -89,66 +68,4 @@ public class HttpGraphQlTransport implements GraphQlTransport { throw new UnsupportedOperationException("Subscriptions not supported over HTTP"); } - - /** - * Static factory method with a {@code WebClient} to use. - */ - public static HttpGraphQlTransport create(WebClient webClient) { - return new HttpGraphQlTransport(webClient); - } - - /** - * Static method to obtain a {@code Builder}. - */ - public static Builder builder(WebClient webClient) { - return new Builder(webClient); - } - - - /** - * Builder for {@link HttpGraphQlTransport} or a {@link GraphQlClient} - * configured with the transport. - */ - public static class Builder { - - private WebClient webClient; - - private Builder(WebClient webClient) { - this.webClient = webClient; - } - - /** - * Set the {@code WebClient} to use. - */ - public Builder webClient(WebClient webClient) { - this.webClient = webClient; - return this; - } - - /** - * Build the {@code HttpGraphQlTransport} instance. - */ - public HttpGraphQlTransport build() { - return new HttpGraphQlTransport(this.webClient); - } - - /** - * Continue on to build a {@link GraphQlClient} configured with the - * transport configured here so far. - */ - public GraphQlClient.Builder configureClient() { - return GraphQlClient.builder(build()); - } - - /** - * Shortcut to build a {@link GraphQlClient} configured with the - * transport configured here. - */ - public GraphQlClient buildClient() { - return GraphQlClient.builder(build()).build(); - } - - } - - } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/TypeRefAdapter.java b/spring-graphql/src/main/java/org/springframework/graphql/client/TypeRefAdapter.java index d227b020..44ba56c0 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/TypeRefAdapter.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/TypeRefAdapter.java @@ -34,6 +34,7 @@ final class TypeRefAdapter extends TypeRef { private final Type type; + TypeRefAdapter(Class clazz) { this.type = clazz; } diff --git a/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java b/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java index 08e4b690..4f6699cf 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/client/WebSocketGraphQlTransport.java @@ -16,7 +16,6 @@ package org.springframework.graphql.client; import java.net.URI; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -24,7 +23,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; -import java.util.function.Supplier; import graphql.ExecutionResult; import graphql.GraphQLError; @@ -40,7 +38,6 @@ import org.springframework.graphql.support.MapExecutionResult; import org.springframework.graphql.support.MapGraphQlError; import org.springframework.graphql.web.webflux.GraphQlWebSocketMessage; import org.springframework.http.HttpHeaders; -import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.CodecConfigurer; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -52,46 +49,11 @@ import org.springframework.web.reactive.socket.client.WebSocketClient; /** * {@link GraphQlTransport} for GraphQL over WebSocket via {@link WebSocketClient}. * - *

Use the builder to initialize the transport and the {@link GraphQlClient} - * in a single chain: - * - *

- * GraphQlClient client =
- * 		WebSocketGraphQlTransport.builder(url, webSocketClient)
- * 				.headers(headers -> ... )
- * 				.buildClient();
- * 
- * - *

Or build the transport and the client separately: - * - *

- * WebSocketGraphQlTransport transport =
- * 		WebSocketGraphQlTransport.builder(url, webSocketClient)
- * 				.headers(headers -> ... )
- * 				.build();
- *
- * GraphQlClient client = GraphQlClient.create(transport);
- * 
- * - *

Once the client is built, you can obtain the underlying transport, mutate - * it, and rebuild transport and client as follows: - * - *

- * WebSocketGraphQlTransport transport = client.getTransport(WebSocketGraphQlTransport.class);
- *
- * if (transport != null) {
- * 	GraphQlClient newClient = transport.mutate()
- *			.headers(headers -> ... )
- * 			.buildClient();
- * }
- * 
- * - * * @author Rossen Stoyanchev * @since 1.0.0 * @see GraphQL over WebSocket protocol */ -public final class WebSocketGraphQlTransport implements GraphQlTransport { +final class WebSocketGraphQlTransport implements GraphQlTransport { private static final Log logger = LogFactory.getLog(WebSocketGraphQlTransport.class); @@ -100,21 +62,16 @@ public final class WebSocketGraphQlTransport implements GraphQlTransport { private final Mono graphQlSessionMono; - private final Supplier mutateBuilder; - - private WebSocketGraphQlTransport( + WebSocketGraphQlTransport( URI uri, HttpHeaders headers, WebSocketClient client, CodecConfigurer codecConfigurer, - @Nullable Object connectionInitPayload, Consumer> connectionAckHandler, - Supplier mutateBuilder) { + @Nullable Object connectionInitPayload, Consumer> connectionAckHandler) { this.graphQlSessionHandler = new GraphQlSessionHandler( codecConfigurer, connectionInitPayload, connectionAckHandler); this.graphQlSessionMono = initGraphQlSession(uri, headers, client, this.graphQlSessionHandler) .cacheInvalidateWhen(GraphQlSession::notifyWhenClosed); - - this.mutateBuilder = mutateBuilder; } private static Mono initGraphQlSession( @@ -167,154 +124,6 @@ public final class WebSocketGraphQlTransport implements GraphQlTransport { return this.graphQlSessionMono.flatMapMany(session -> session.executeSubscription(request)); } - /** - * Create a builder initialized from the configuration of "this" transport. - * Use this to build a new instance configured differently. - */ - public Builder mutate() { - return this.mutateBuilder.get(); - } - - - /** - * Static factory method with the client and the endpoint to connect to. - * @param uri the WebSocket handshake URL - * @param client the WebSocket client - * @return the created instance - */ - public static WebSocketGraphQlTransport create(URI uri, WebSocketClient client) { - return new Builder(uri, client).build(); - } - - /** - * Return a builder with further options for the transport. - * @param uri the WebSocket handshake URL - * @param client the WebSocket client - * @return the builder instance - */ - public static Builder builder(URI uri, WebSocketClient client) { - return new Builder(uri, client); - } - - - /** - * Builder for {@link WebSocketGraphQlTransport} with an option to build a - * {@link GraphQlClient} instead, configured with the transport. - */ - public static final class Builder { - - private URI url; - - private final HttpHeaders headers = new HttpHeaders(); - - private WebSocketClient client; - - private CodecConfigurer codecsConfigurer = ClientCodecConfigurer.create(); - - @Nullable - private Object initPayload; - - private Consumer> connectionAckHandler = ackPayload -> {}; - - - Builder(URI url, WebSocketClient client) { - this.url = url; - this.client = client; - } - - - /** - * Set the URL for the WebSocket handshake request. - */ - public Builder url(URI uri) { - Assert.notNull(uri, "URI is required"); - this.url = uri; - return this; - } - - /** - * Add an HTTP header for the WebSocket handshake request. - */ - public Builder header(String name, String... values) { - Arrays.stream(values).forEach(value -> this.headers.add(name, value)); - return this; - } - - /** - * Provides access to every header declared so far with the possibility - * to add, replace, or remove. - */ - public Builder headers(Consumer headersConsumer) { - headersConsumer.accept(this.headers); - return this; - } - - /** - * Set the {@code WebSocketClient} to connect over. - */ - public Builder webSocketClient(WebSocketClient client) { - Assert.notNull(client, "WebSocketClient is required"); - this.client = client; - return this; - } - - /** - * Provide a {@code CodecConfigurer} that should contain encoders and - * decoders for JSON to be able to encode and decode GraphQL messages. - */ - public Builder codecConfigurer(CodecConfigurer codecConfigurer) { - this.codecsConfigurer = codecConfigurer; - return this; - } - - /** - * The payload to send with the "connection_init" message. - */ - public Builder connectionInitPayload(@Nullable Object connectionInitPayload) { - this.initPayload = connectionInitPayload; - return this; - } - - /** - * Handler for the payload received with the "connection_ack" message. - */ - public Builder connectionAckHandler(Consumer> ackHandler) { - this.connectionAckHandler = ackHandler; - return this; - } - - /** - * Build the transport instance. - */ - public WebSocketGraphQlTransport build() { - - Supplier mutateBuilder = () -> new Builder(this.url, this.client) - .headers(theHeaders -> theHeaders.putAll(this.headers)) - .codecConfigurer(codecsConfigurer.clone()) - .connectionInitPayload(this.initPayload) - .connectionAckHandler(this.connectionAckHandler); - - return new WebSocketGraphQlTransport(this.url, this.headers, this.client, - this.codecsConfigurer, this.initPayload, this.connectionAckHandler, mutateBuilder); - } - - /** - * Proceed to build a client that is configured with the transport from - * this builder. - */ - public GraphQlClient.Builder configureClient() { - return GraphQlClient.builder(build()); - } - - /** - * Build a client configured with the transport from this builder. - */ - public GraphQlClient buildClient() { - return GraphQlClient.builder(build()).build(); - } - - } - /** * Client {@code WebSocketHandler} for GraphQL that deals with WebSocket diff --git a/spring-graphql/src/main/java/org/springframework/graphql/support/DocumentSource.java b/spring-graphql/src/main/java/org/springframework/graphql/support/DocumentSource.java index 26028d64..a4e203dc 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/support/DocumentSource.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/support/DocumentSource.java @@ -28,7 +28,8 @@ public interface DocumentSource { /** * Return the document that matches the given name. * @param name the name to use for the lookup - * @return {@code Mono} that provides the document or returns an error + * @return {@code Mono} that completes either with the document content or + * with an error, but never empty. */ Mono getDocument(String name);