Skip to content

Commit 6e79dcd

Browse files
committed
Merge pull request #23070 from L00kian/23060-fix
2 parents ac29e9d + 29b7659 commit 6e79dcd

File tree

2 files changed

+73
-15
lines changed

2 files changed

+73
-15
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/RequestPartMethodArgumentResolver.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 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.
@@ -96,19 +96,12 @@ public Mono<Object> resolveArgument(
9696

9797
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
9898
if (adapter != null) {
99-
// Mono<Part> or Flux<Part>
10099
MethodParameter elementType = parameter.nested();
101-
if (Part.class.isAssignableFrom(elementType.getNestedParameterType())) {
102-
parts = (adapter.isMultiValue() ? parts : parts.take(1));
103-
return Mono.just(adapter.fromPublisher(parts));
104-
}
105-
// We have to decode the content for each part, one at a time
106-
if (adapter.isMultiValue()) {
107-
return Mono.just(decodePartValues(parts, elementType, bindingContext, exchange, isRequired));
108-
}
100+
return Mono.just(adapter.fromPublisher(
101+
Part.class.isAssignableFrom(elementType.getNestedParameterType()) ?
102+
parts : decodePartValues(parts, elementType, bindingContext, exchange, isRequired)));
109103
}
110104

111-
// <T> or Mono<T>
112105
return decodePartValues(parts, parameter, bindingContext, exchange, isRequired)
113106
.next().cast(Object.class);
114107
}

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestPartMethodArgumentResolverTests.java

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 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.
@@ -53,13 +53,18 @@
5353
import org.springframework.web.server.ServerWebExchange;
5454
import org.springframework.web.server.ServerWebInputException;
5555

56-
import static org.junit.Assert.*;
57-
import static org.springframework.core.ResolvableType.*;
58-
import static org.springframework.web.method.MvcAnnotationPredicates.*;
56+
import static org.junit.Assert.assertEquals;
57+
import static org.junit.Assert.assertFalse;
58+
import static org.junit.Assert.assertNotNull;
59+
import static org.junit.Assert.assertNull;
60+
import static org.junit.Assert.assertTrue;
61+
import static org.springframework.core.ResolvableType.forClass;
62+
import static org.springframework.web.method.MvcAnnotationPredicates.requestPart;
5963

6064
/**
6165
* Unit tests for {@link RequestPartMethodArgumentResolver}.
6266
* @author Rossen Stoyanchev
67+
* @author Ilya Lukyanovich
6368
*/
6469
public class RequestPartMethodArgumentResolverTests {
6570

@@ -131,6 +136,15 @@ public void listPerson() {
131136
assertEquals("James", actual.get(1).getName());
132137
}
133138

139+
@Test // gh-23060
140+
public void listPersonNotRequired() {
141+
MethodParameter param = this.testMethod.annot(requestPart().notRequired()).arg(List.class, Person.class);
142+
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
143+
List<Person> actual = resolveArgument(param, bodyBuilder);
144+
145+
assertEquals(Collections.emptyList(), actual);
146+
}
147+
134148
@Test
135149
public void monoPerson() {
136150
MethodParameter param = this.testMethod.annot(requestPart()).arg(Mono.class, Person.class);
@@ -141,6 +155,15 @@ public void monoPerson() {
141155
assertEquals("Jones", actual.block().getName());
142156
}
143157

158+
@Test // gh-23060
159+
public void monoPersonNotRequired() {
160+
MethodParameter param = this.testMethod.annot(requestPart().notRequired()).arg(Mono.class, Person.class);
161+
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
162+
Mono<Person> actual = resolveArgument(param, bodyBuilder);
163+
164+
assertNull(actual.block());
165+
}
166+
144167
@Test
145168
public void fluxPerson() {
146169
MethodParameter param = this.testMethod.annot(requestPart()).arg(Flux.class, Person.class);
@@ -154,6 +177,15 @@ public void fluxPerson() {
154177
assertEquals("James", persons.get(1).getName());
155178
}
156179

180+
@Test // gh-23060
181+
public void fluxPersonNotRequired() {
182+
MethodParameter param = this.testMethod.annot(requestPart().notRequired()).arg(Flux.class, Person.class);
183+
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
184+
Flux<Person> actual = resolveArgument(param, bodyBuilder);
185+
186+
assertEquals(Collections.emptyList(), actual.collectList().block());
187+
}
188+
157189
@Test
158190
public void part() {
159191
MethodParameter param = this.testMethod.annot(requestPart()).arg(Part.class);
@@ -177,6 +209,15 @@ public void listPart() {
177209
assertEquals("{\"name\":\"James\"}", partToUtf8String(actual.get(1)));
178210
}
179211

212+
@Test // gh-23060
213+
public void listPartNotRequired() {
214+
MethodParameter param = this.testMethod.annot(requestPart().notRequired()).arg(List.class, Part.class);
215+
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
216+
List<Part> actual = resolveArgument(param, bodyBuilder);
217+
218+
assertEquals(Collections.emptyList(), actual);
219+
}
220+
180221
@Test
181222
public void monoPart() {
182223
MethodParameter param = this.testMethod.annot(requestPart()).arg(Mono.class, Part.class);
@@ -188,6 +229,15 @@ public void monoPart() {
188229
assertEquals("{\"name\":\"Jones\"}", partToUtf8String(part));
189230
}
190231

232+
@Test // gh-23060
233+
public void monoPartNotRequired() {
234+
MethodParameter param = this.testMethod.annot(requestPart().notRequired()).arg(Mono.class, Part.class);
235+
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
236+
Mono<Part> actual = resolveArgument(param, bodyBuilder);
237+
238+
assertNull(actual.block());
239+
}
240+
191241
@Test
192242
public void fluxPart() {
193243
MethodParameter param = this.testMethod.annot(requestPart()).arg(Flux.class, Part.class);
@@ -201,6 +251,15 @@ public void fluxPart() {
201251
assertEquals("{\"name\":\"James\"}", partToUtf8String(parts.get(1)));
202252
}
203253

254+
@Test // gh-23060
255+
public void fluxPartNotRequired() {
256+
MethodParameter param = this.testMethod.annot(requestPart().notRequired()).arg(Flux.class, Part.class);
257+
MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder();
258+
Flux<Part> actual = resolveArgument(param, bodyBuilder);
259+
260+
assertEquals(Collections.emptyList(), actual.collectList().block());
261+
}
262+
204263
@Test
205264
public void personRequired() {
206265
MethodParameter param = this.testMethod.annot(requestPart()).arg(Person.class);
@@ -278,7 +337,13 @@ void handle(
278337
@RequestPart("name") Flux<Part> partFlux,
279338
@RequestPart("name") List<Part> partList,
280339
@RequestPart(name = "anotherPart", required = false) Person anotherPerson,
340+
@RequestPart(name = "name", required = false) Mono<Person> anotherPersonMono,
341+
@RequestPart(name = "name", required = false) Flux<Person> anotherPersonFlux,
342+
@RequestPart(name = "name", required = false) List<Person> anotherPersonList,
281343
@RequestPart(name = "anotherPart", required = false) Part anotherPart,
344+
@RequestPart(name = "name", required = false) Mono<Part> anotherPartMono,
345+
@RequestPart(name = "name", required = false) Flux<Part> anotherPartFlux,
346+
@RequestPart(name = "name", required = false) List<Part> anotherPartList,
282347
Person notAnnotated) {}
283348

284349

0 commit comments

Comments
 (0)