From db55ee2c2cc94a5f9a3fe50a07478cedc40659f4 Mon Sep 17 00:00:00 2001 From: Spring Builds Date: Tue, 21 Mar 2023 10:22:40 +0000 Subject: [PATCH 1/4] Next development version (v1.1.4-SNAPSHOT) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e7547ad6..ca5a6bae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=1.1.3-SNAPSHOT +version=1.1.4-SNAPSHOT org.gradle.caching=true org.gradle.daemon=true From 4a0d01a33b8e4593aa0235bc4ee941b850affa98 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Fri, 14 Apr 2023 06:55:36 +0100 Subject: [PATCH 2/4] Fix auto-registration issue with non-null List Closes gh-661 --- ...toRegistrationRuntimeWiringConfigurer.java | 25 +++++++++++-------- .../src/test/resources/books/schema.graphqls | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java b/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java index 0306e5a0..16c3f39a 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/query/AutoRegistrationRuntimeWiringConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -112,16 +112,21 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer @Nullable private String getOutputTypeName(FieldWiringEnvironment environment) { - GraphQLType outputType = (environment.getFieldType() instanceof GraphQLList ? - ((GraphQLList) environment.getFieldType()).getWrappedType() : - environment.getFieldType()); + GraphQLType outputType = removeNonNullWrapper(environment.getFieldType()); - if (outputType instanceof GraphQLNonNull) { - outputType = ((GraphQLNonNull) outputType).getWrappedType(); + if (outputType instanceof GraphQLList) { + outputType = removeNonNullWrapper(((GraphQLList) outputType).getWrappedType()); } - return (outputType instanceof GraphQLNamedOutputType ? - ((GraphQLNamedOutputType) outputType).getName() : null); + if (outputType instanceof GraphQLNamedOutputType namedType) { + return namedType.getName(); + } + + return null; + } + + private GraphQLType removeNonNullWrapper(GraphQLType outputType) { + return (outputType instanceof GraphQLNonNull wrapper ? wrapper.getWrappedType() : outputType); } private boolean hasDataFetcherFor(FieldDefinition fieldDefinition) { @@ -152,8 +157,8 @@ class AutoRegistrationRuntimeWiringConfigurer implements RuntimeWiringConfigurer Function> factory = dataFetcherFactories.get(outputTypeName); Assert.notNull(factory, "Expected DataFetcher factory for typeName '" + outputTypeName + "'"); - boolean single = !(environment.getFieldType() instanceof GraphQLList); - return factory.apply(single); + GraphQLType type = removeNonNullWrapper(environment.getFieldType()); + return factory.apply(!(type instanceof GraphQLList)); } } diff --git a/spring-graphql/src/test/resources/books/schema.graphqls b/spring-graphql/src/test/resources/books/schema.graphqls index 0f98f5f6..e1d7bcdd 100644 --- a/spring-graphql/src/test/resources/books/schema.graphqls +++ b/spring-graphql/src/test/resources/books/schema.graphqls @@ -1,7 +1,7 @@ type Query { bookById(id: ID): Book booksById(id: [ID]): [Book] - books(id: ID, name: String, author: String): [Book!] + books(id: ID, name: String, author: String): [Book!]! booksByCriteria(criteria:BookCriteria): [Book] booksByProjectedArguments(name: String, author: String): [Book] booksByProjectedCriteria(criteria:BookCriteria): [Book] From b7d1e6e9d23bd247b62f39ba3773fc486cbfc745 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Thu, 13 Apr 2023 17:59:18 +0100 Subject: [PATCH 3/4] Pass attributes in HttpGraphQlTransport Closes gh-659 --- .../graphql/client/HttpGraphQlTransport.java | 7 +++- .../client/WebGraphQlClientBuilderTests.java | 35 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) 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 98f340d9..70af28a9 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -75,6 +75,11 @@ final class HttpGraphQlTransport implements GraphQlTransport { .contentType(this.contentType) .accept(MediaType.APPLICATION_JSON, APPLICATION_GRAPHQL_RESPONSE, MediaType.APPLICATION_GRAPHQL) .bodyValue(request.toMap()) + .attributes(attributes -> { + if (request instanceof ClientGraphQlRequest clientRequest) { + attributes.putAll(clientRequest.getAttributes()); + } + }) .retrieve() .bodyToMono(MAP_TYPE) .map(ResponseMapGraphQlResponse::new); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java b/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java index 444d5873..a825d91c 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/client/WebGraphQlClientBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -20,6 +20,7 @@ import java.net.URI; import java.time.Duration; import java.util.Collections; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; import graphql.ExecutionResultImpl; @@ -47,6 +48,9 @@ import org.springframework.lang.Nullable; import org.springframework.test.web.reactive.server.HttpHandlerConnector; import org.springframework.util.Assert; import org.springframework.util.MimeType; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.ExchangeFunction; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.server.HandlerStrategies; import org.springframework.web.reactive.function.server.RouterFunction; @@ -227,6 +231,20 @@ public class WebGraphQlClientBuilderTests { assertThat(testDecoder.getLastValue()).isEqualTo(character); } + @Test + void attributes() { + + HttpBuilderSetup builderSetup = new HttpBuilderSetup(); + + builderSetup.initBuilder().url("/graphql-one").headers(headers -> headers.add("h", "one")).build() + .document(DOCUMENT) + .attribute("id", 123) + .execute() + .block(TIMEOUT); + + assertThat(builderSetup.getClientAttributes()).containsEntry("id", 123); + } + private interface ClientBuilderSetup { @@ -275,13 +293,26 @@ public class WebGraphQlClientBuilderTests { private static class HttpBuilderSetup extends AbstractBuilderSetup { + private final Map clientAttributes = new ConcurrentHashMap<>(); + + public Map getClientAttributes() { + return this.clientAttributes; + } + @Override public HttpGraphQlClient.Builder initBuilder() { GraphQlHttpHandler handler = new GraphQlHttpHandler(webGraphQlHandler()); RouterFunction routerFunction = route().POST("/**", handler::handleRequest).build(); HttpHandler httpHandler = RouterFunctions.toHttpHandler(routerFunction, HandlerStrategies.withDefaults()); HttpHandlerConnector connector = new HttpHandlerConnector(httpHandler); - return HttpGraphQlClient.builder(WebClient.builder().clientConnector(connector)); + return HttpGraphQlClient.builder(WebClient.builder() + .clientConnector(connector).filter(this::updateAttributes)); + } + + private Mono updateAttributes(ClientRequest request, ExchangeFunction next) { + this.clientAttributes.clear(); + this.clientAttributes.putAll(request.attributes()); + return next.exchange(request); } } From c650db895b89ba683b45acd54008b02a14c364a3 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Fri, 14 Apr 2023 08:27:17 +0100 Subject: [PATCH 4/4] Add link in documentation to Apollo federation sample Closes gh-384 --- spring-graphql-docs/src/docs/asciidoc/index.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index 316bf49a..89fbdbac 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -260,6 +260,9 @@ builder.schemaResources(..) The <> 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]. + [[execution.graphqlsource.schema-traversal]] ==== Schema Traversal