Skip to content

Commit 01a69fa

Browse files
committed
Merge branch '1.0.x'
2 parents d8e1402 + 257f309 commit 01a69fa

File tree

7 files changed

+102
-27
lines changed

7 files changed

+102
-27
lines changed

spring-graphql-docs/src/docs/asciidoc/client.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ For example, given a file called `projectReleases.graphql` in
320320
`src/main/resources/graphql-documents`, with content:
321321

322322
[source,graphql,indent=0,subs="verbatim,quotes"]
323-
.src/main/resources/graphql/project.graphql
323+
.src/main/resources/graphql-documents/projectReleases.graphql
324324
----
325325
query projectReleases($slug: ID!) {
326326
project(slug: $slug) {
@@ -341,7 +341,7 @@ You can then:
341341
.retrieve()
342342
.toEntity(Project.class);
343343
----
344-
<1> Load the document from "project.graphql"
344+
<1> Load the document from "projectReleases.graphql"
345345
<2> Provide variable values.
346346

347347
The "JS GraphQL" plugin for IntelliJ supports GraphQL query files with code completion.

spring-graphql/src/main/java/org/springframework/graphql/data/GraphQlArgumentBinder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ private <T> Collection<T> createCollection(
213213
int i = 0;
214214
for (Object rawValue : rawCollection) {
215215
segments.push("[" + i++ + "]");
216-
if (elementClass.isAssignableFrom(rawValue.getClass())) {
216+
if (rawValue == null || elementClass.isAssignableFrom(rawValue.getClass())) {
217217
collection.add((T) rawValue);
218218
}
219219
else if (rawValue instanceof Map) {

spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphiQlHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2021 the original author or authors.
2+
* Copyright 2020-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -86,7 +86,7 @@ private URI getRedirectUrl(ServerRequest request) {
8686
String wsPathQueryParam = applyContextPath(request, this.graphQlWsPath);
8787
builder.queryParam("wsPath", wsPathQueryParam);
8888
}
89-
return builder.build();
89+
return builder.build(request.pathVariables());
9090
}
9191

9292
private String applyContextPath(ServerRequest request, String path) {

spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphiQlHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2021 the original author or authors.
2+
* Copyright 2020-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -85,7 +85,7 @@ private URI getRedirectUrl(ServerRequest request) {
8585
String wsPathQueryParam = applyPathPrefix(request, this.graphQlWsPath);
8686
builder.queryParam("wsPath", wsPathQueryParam);
8787
}
88-
return builder.build();
88+
return builder.build(request.pathVariables());
8989
}
9090

9191
private String applyPathPrefix(ServerRequest request, String path) {

spring-graphql/src/test/java/org/springframework/graphql/data/GraphQlArgumentBinderTests.java

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,14 @@
1616

1717
package org.springframework.graphql.data;
1818

19-
import java.util.ArrayList;
2019
import java.util.Collections;
2120
import java.util.HashMap;
22-
import java.util.HashSet;
2321
import java.util.List;
2422
import java.util.Map;
2523
import java.util.Objects;
2624
import java.util.Set;
2725
import java.util.stream.Collectors;
2826
import java.util.stream.IntStream;
29-
import java.util.stream.Stream;
3027

3128
import com.fasterxml.jackson.core.JsonProcessingException;
3229
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -36,9 +33,6 @@
3633

3734
import org.springframework.core.ResolvableType;
3835
import org.springframework.graphql.Book;
39-
import org.springframework.graphql.data.GraphQlArgumentBinder;
40-
import org.springframework.util.ReflectionUtils;
41-
import org.springframework.util.StringUtils;
4236
import org.springframework.validation.BindException;
4337
import org.springframework.validation.FieldError;
4438

@@ -60,7 +54,7 @@ class GraphQlArgumentBinderTests {
6054

6155

6256
@Test
63-
void defaultConstructor() throws Exception {
57+
void dataBinding() throws Exception {
6458

6559
Object result = this.binder.bind(
6660
environment("{\"key\":{\"name\":\"test\"}}"), "key",
@@ -71,7 +65,7 @@ void defaultConstructor() throws Exception {
7165
}
7266

7367
@Test
74-
void defaultConstructorWithNestedBeanProperty() throws Exception {
68+
void dataBindingWithNestedBeanProperty() throws Exception {
7569

7670
Object result = this.binder.bind(
7771
environment(
@@ -92,7 +86,7 @@ void defaultConstructorWithNestedBeanProperty() throws Exception {
9286
}
9387

9488
@Test
95-
void defaultConstructorWithNestedBeanListProperty() throws Exception {
89+
void dataBindingWithNestedBeanListProperty() throws Exception {
9690

9791
Object result = this.binder.bind(
9892
environment("{\"key\":{\"items\":[{\"name\":\"first\"},{\"name\":\"second\"}]}}"), "key",
@@ -104,7 +98,7 @@ void defaultConstructorWithNestedBeanListProperty() throws Exception {
10498
}
10599

106100
@Test // gh-301
107-
void defaultConstructorWithNestedBeanListEmpty() throws Exception {
101+
void dataBindingWithNestedBeanListEmpty() throws Exception {
108102

109103
Object result = this.binder.bind(
110104
environment("{\"key\":{\"items\": []}}"), "key",
@@ -115,7 +109,7 @@ void defaultConstructorWithNestedBeanListEmpty() throws Exception {
115109
}
116110

117111
@Test // gh-280
118-
void defaultConstructorBindingError() {
112+
void dataBindingBindingError() {
119113

120114
assertThatThrownBy(
121115
() -> this.binder.bind(
@@ -130,6 +124,35 @@ void defaultConstructorBindingError() {
130124
});
131125
}
132126

127+
@Test
128+
@SuppressWarnings("unchecked")
129+
void dataBindingToList() throws Exception {
130+
131+
Object result = this.binder.bind(
132+
environment("{\"key\": [\"1\", \"2\", \"3\"]}"), "key",
133+
ResolvableType.forClassWithGenerics(List.class, String.class));
134+
135+
assertThat(result).isNotNull().isInstanceOf(List.class);
136+
assertThat((List<String>) result).containsExactly("1", "2", "3");
137+
138+
// gh-486: List with null element
139+
result = this.binder.bind(
140+
environment("{\"key\": [\"1\", null, \"3\"]}"), "key",
141+
ResolvableType.forClassWithGenerics(List.class, String.class));
142+
143+
assertThat(result).isNotNull().isInstanceOf(List.class);
144+
assertThat((List<String>) result).containsExactly("1", null, "3");
145+
146+
// Empty list
147+
148+
result = this.binder.bind(
149+
environment("{\"key\": []}"), "key",
150+
ResolvableType.forClassWithGenerics(List.class, String.class));
151+
152+
assertThat(result).isNotNull().isInstanceOf(List.class);
153+
assertThat((List<String>) result).isEmpty();
154+
}
155+
133156
@Test
134157
void primaryConstructor() throws Exception {
135158

@@ -261,7 +284,6 @@ void coercionWithSingletonList() throws Exception {
261284
}
262285

263286
@Test // gh-392
264-
@SuppressWarnings("unchecked")
265287
void shouldHaveHigherDefaultAutoGrowLimit() throws Exception {
266288
String items = IntStream.range(0, 260).mapToObj(value -> "{\"name\":\"test\"}").collect(Collectors.joining(","));
267289
Object result = this.binder.bind(
@@ -281,7 +303,6 @@ void shouldUseTargetCollectionType() throws Exception {
281303
assertThat(((ItemSetHolder) result).getItems()).hasSize(5);
282304
}
283305

284-
285306
@SuppressWarnings("unchecked")
286307
private DataFetchingEnvironment environment(String jsonPayload) throws JsonProcessingException {
287308
Map<String, Object> arguments = this.mapper.readValue(jsonPayload, Map.class);

spring-graphql/src/test/java/org/springframework/graphql/server/webflux/GraphiQlHandlerTests.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.nio.charset.StandardCharsets;
2020
import java.util.Collections;
2121
import java.util.List;
22+
import java.util.Map;
2223

2324
import org.junit.jupiter.api.Test;
2425

@@ -31,9 +32,11 @@
3132
import org.springframework.http.codec.HttpMessageWriter;
3233
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
3334
import org.springframework.mock.web.server.MockServerWebExchange;
35+
import org.springframework.web.reactive.function.server.RouterFunctions;
3436
import org.springframework.web.reactive.function.server.ServerRequest;
3537
import org.springframework.web.reactive.function.server.ServerResponse;
3638
import org.springframework.web.reactive.result.view.ViewResolver;
39+
import org.springframework.web.util.UriComponentsBuilder;
3740

3841
import static org.assertj.core.api.Assertions.assertThat;
3942

@@ -45,10 +48,13 @@ class GraphiQlHandlerTests {
4548

4649
private static final List<HttpMessageReader<?>> MESSAGE_READERS = Collections.emptyList();
4750

48-
private final GraphiQlHandler handler = new GraphiQlHandler("/graphql", null,
49-
new ByteArrayResource("GRAPHIQL".getBytes(StandardCharsets.UTF_8)));
51+
private final GraphiQlHandler handler = initHandler("/graphql");
5052

5153

54+
private static GraphiQlHandler initHandler(String path) {
55+
return new GraphiQlHandler(path, null, new ByteArrayResource("GRAPHIQL".getBytes(StandardCharsets.UTF_8)));
56+
}
57+
5258
@Test
5359
void shouldRedirectWithPathQueryParameter() {
5460
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/graphiql").build();
@@ -73,6 +79,25 @@ void shouldRedirectWithPathAndWsPathQueryParameter() {
7379
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("/graphiql?path=/graphql&wsPath=/graphql");
7480
}
7581

82+
@Test // gh-478
83+
void shouldRedirectWithPathVariables() {
84+
Map<String, Object> pathVariables = Collections.singletonMap("envId", "123");
85+
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString("/env/{envId}/graphiql");
86+
String path = uriBuilder.build(pathVariables).toString();
87+
88+
MockServerHttpRequest httpRequest = MockServerHttpRequest.get(path).build();
89+
MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest);
90+
exchange.getAttributes().put(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables);
91+
ServerRequest request = ServerRequest.create(exchange, MESSAGE_READERS);
92+
93+
GraphiQlHandler graphiQlHandler = initHandler(uriBuilder.build().toString());
94+
ServerResponse response = graphiQlHandler.handleRequest(request).block();
95+
96+
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
97+
assertThat(response.headers().getLocation()).isNotNull();
98+
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo(path + "?path=" + path);
99+
}
100+
76101
@Test
77102
void shouldServeGraphiQlHtmlResource() {
78103
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("/graphiql").queryParam("path", "/graphql").build();

spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphiQlHandlerTests.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.nio.charset.StandardCharsets;
2222
import java.util.Collections;
2323
import java.util.List;
24+
import java.util.Map;
2425

2526
import jakarta.servlet.ServletException;
2627
import jakarta.servlet.http.MappingMatch;
@@ -35,9 +36,11 @@
3536
import org.springframework.mock.web.MockHttpServletMapping;
3637
import org.springframework.mock.web.MockHttpServletRequest;
3738
import org.springframework.mock.web.MockHttpServletResponse;
39+
import org.springframework.web.servlet.function.RouterFunctions;
3840
import org.springframework.web.servlet.function.ServerRequest;
3941
import org.springframework.web.servlet.function.ServerResponse;
4042
import org.springframework.web.util.ServletRequestPathUtils;
43+
import org.springframework.web.util.UriComponentsBuilder;
4144

4245
import static org.assertj.core.api.Assertions.assertThat;
4346

@@ -50,8 +53,13 @@ class GraphiQlHandlerTests {
5053

5154
private static final List<HttpMessageConverter<?>> MESSAGE_READERS = Collections.emptyList();
5255

53-
private GraphiQlHandler handler = new GraphiQlHandler("/graphql", null,
54-
new ByteArrayResource("GRAPHIQL".getBytes(StandardCharsets.UTF_8)));
56+
private final GraphiQlHandler handler = initHandler("/graphql");
57+
58+
59+
private static GraphiQlHandler initHandler(String path) {
60+
return new GraphiQlHandler(path, null, new ByteArrayResource("GRAPHIQL".getBytes(StandardCharsets.UTF_8)));
61+
}
62+
5563

5664
@Test
5765
void shouldRedirectWithPathQueryParameter() {
@@ -60,7 +68,8 @@ void shouldRedirectWithPathQueryParameter() {
6068
ServerResponse response = this.handler.handleRequest(request);
6169
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
6270
assertThat(response.headers().getLocation()).isNotNull();
63-
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("http://localhost/graphiql?path=/graphql");
71+
assertThat(response.headers().getLocation().toASCIIString())
72+
.isEqualTo("http://localhost/graphiql?path=/graphql");
6473
}
6574

6675
@Test
@@ -72,7 +81,27 @@ void shouldRedirectWithPathAndWsPathQueryParameter() {
7281
ServerResponse response = wsHandler.handleRequest(request);
7382
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
7483
assertThat(response.headers().getLocation()).isNotNull();
75-
assertThat(response.headers().getLocation().toASCIIString()).isEqualTo("http://localhost/graphiql?path=/graphql&wsPath=/graphql");
84+
assertThat(response.headers().getLocation().toASCIIString())
85+
.isEqualTo("http://localhost/graphiql?path=/graphql&wsPath=/graphql");
86+
}
87+
88+
@Test // gh-478
89+
void shouldRedirectWithPathVariables() {
90+
Map<String, Object> pathVariables = Collections.singletonMap("envId", "123");
91+
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString("/env/{envId}/graphiql");
92+
String path = uriBuilder.build(pathVariables).toString();
93+
94+
MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", path);
95+
ServerRequest request = ServerRequest.create(servletRequest, MESSAGE_READERS);
96+
servletRequest.setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables);
97+
98+
GraphiQlHandler graphiQlHandler = initHandler(uriBuilder.build().toString());
99+
ServerResponse response = graphiQlHandler.handleRequest(request);
100+
101+
assertThat(response.statusCode()).isEqualTo(HttpStatus.TEMPORARY_REDIRECT);
102+
assertThat(response.headers().getLocation()).isNotNull();
103+
assertThat(response.headers().getLocation().toASCIIString())
104+
.isEqualTo("http://localhost" + path + "?path=" + path);
76105
}
77106

78107
@Test
@@ -129,4 +158,4 @@ public List<HttpMessageConverter<?>> messageConverters() {
129158

130159
}
131160

132-
}
161+
}

0 commit comments

Comments
 (0)