Skip to content

Commit e0b4058

Browse files
committed
Merge branch '5.3.x'
2 parents 479a53b + f9d8367 commit e0b4058

File tree

8 files changed

+68
-37
lines changed

8 files changed

+68
-37
lines changed

framework-docs/src/docs/asciidoc/web/webflux.adoc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,10 +2015,9 @@ generally supported for all return values.
20152015
to be written (however, `text/event-stream` must be requested or declared in the mapping
20162016
through the `produces` attribute).
20172017

2018-
| Any other return value
2019-
| If a return value is not matched to any of the above, it is, by default, treated as a view
2020-
name, if it is `String` or `void` (default view name selection applies), or as a model
2021-
attribute to be added to the model, unless it is a simple type, as determined by
2018+
| Other return values
2019+
| If a return value remains unresolved in any other way, it is treated as a model
2020+
attribute, unless it is a simple type as determined by
20222021
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty],
20232022
in which case it remains unresolved.
20242023
|===

framework-docs/src/docs/asciidoc/web/webmvc.adoc

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,23 +2282,18 @@ supported for all return values.
22822282
| Write to the response `OutputStream` asynchronously. Also supported as the body of a
22832283
`ResponseEntity`. See <<mvc-ann-async>> and <<mvc-ann-async-http-streaming>>.
22842284

2285-
| Reactive types -- Reactor, RxJava, or others through `ReactiveAdapterRegistry`
2286-
| Alternative to `DeferredResult` with multi-value streams (for example, `Flux`, `Observable`)
2287-
collected to a `List`.
2288-
2289-
For streaming scenarios (for example, `text/event-stream`, `application/json+stream`),
2290-
`SseEmitter` and `ResponseBodyEmitter` are used instead, where `ServletOutputStream`
2291-
blocking I/O is performed on a Spring MVC-managed thread and back pressure is applied
2292-
against the completion of each write.
2293-
2294-
See <<mvc-ann-async>> and <<mvc-ann-async-reactive-types>>.
2295-
2296-
| Any other return value
2297-
| Any return value that does not match any of the earlier values in this table and that
2298-
is a `String` or `void` is treated as a view name (default view name selection through
2299-
`RequestToViewNameTranslator` applies), provided it is not a simple type, as determined by
2300-
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty].
2301-
Values that are simple types remain unresolved.
2285+
| Reactor and other reactive types registered via `ReactiveAdapterRegistry`
2286+
| A single value type, e.g. `Mono`, is comparable to returning `DeferredResult`.
2287+
A multi-value type, e.g. `Flux`, may be treated as a stream depending on the requested
2288+
media type, e.g. "text/event-stream", "application/json+stream", or otherwise is
2289+
collected to a List and rendered as a single value. See <<mvc-ann-async>> and
2290+
<<mvc-ann-async-reactive-types>>.
2291+
2292+
| Other return values
2293+
| If a return value remains unresolved in any other way, it is treated as a model
2294+
attribute, unless it is a simple type as determined by
2295+
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty],
2296+
in which case it remains unresolved.
23022297
|===
23032298

23042299

spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-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.
@@ -54,6 +54,10 @@ public abstract class InterceptingHttpAccessor extends HttpAccessor {
5454
* Set the request interceptors that this accessor should use.
5555
* <p>The interceptors will get immediately sorted according to their
5656
* {@linkplain AnnotationAwareOrderComparator#sort(List) order}.
57+
* <p><strong>Note:</strong> This method does not support concurrent changes,
58+
* and in most cases should not be called after initialization on startup.
59+
* See also related note on {@link org.springframework.web.client.RestTemplate}
60+
* regarding concurrent configuration changes.
5761
* @see #getRequestFactory()
5862
* @see AnnotationAwareOrderComparator
5963
*/

spring-web/src/main/java/org/springframework/web/client/RestTemplate.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,17 @@
7878
/**
7979
* Synchronous client to perform HTTP requests, exposing a simple, template
8080
* method API over underlying HTTP client libraries such as the JDK
81-
* {@code HttpURLConnection}, Apache HttpComponents, and others.
81+
* {@code HttpURLConnection}, Apache HttpComponents, and others. RestTemplate
82+
* offers templates for common scenarios by HTTP method, in addition to the
83+
* generalized {@code exchange} and {@code execute} methods that support of
84+
* less frequent cases.
8285
*
83-
* <p>The RestTemplate offers templates for common scenarios by HTTP method, in
84-
* addition to the generalized {@code exchange} and {@code execute} methods that
85-
* support of less frequent cases.
86+
* <p>RestTemplate is typically used as a shared component. However, its
87+
* configuration does not support concurrent modification, and as such its
88+
* configuration is typically prepared on startup. If necessary, you can create
89+
* multiple, differently configured RestTemplate instances on startup. Such
90+
* instances may use the same the underlying {@link ClientHttpRequestFactory}
91+
* if they need to share HTTP client resources.
8692
*
8793
* <p><strong>NOTE:</strong> As of 5.0 this class is in maintenance mode, with
8894
* only minor requests for changes and bugs to be accepted going forward. Please,

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.web.reactive.function.client;
1818

1919
import java.net.URI;
20+
import java.net.URISyntaxException;
2021
import java.nio.charset.Charset;
2122
import java.time.ZonedDateTime;
2223
import java.util.ArrayList;
@@ -53,6 +54,7 @@
5354
import org.springframework.util.CollectionUtils;
5455
import org.springframework.util.LinkedMultiValueMap;
5556
import org.springframework.util.MultiValueMap;
57+
import org.springframework.util.StringUtils;
5658
import org.springframework.web.reactive.function.BodyExtractor;
5759
import org.springframework.web.reactive.function.BodyInserter;
5860
import org.springframework.web.reactive.function.BodyInserters;
@@ -713,10 +715,22 @@ private <T> Mono<T> applyStatusHandlers(ClientResponse response) {
713715
}
714716

715717
private <T> Mono<T> insertCheckpoint(Mono<T> result, HttpStatusCode statusCode, HttpRequest request) {
716-
HttpMethod httpMethod = request.getMethod();
718+
HttpMethod method = request.getMethod();
719+
URI uri = getUriToLog(request);
720+
return result.checkpoint(statusCode + " from " + method + " " + uri + " [DefaultWebClient]");
721+
}
722+
723+
private static URI getUriToLog(HttpRequest request) {
717724
URI uri = request.getURI();
718-
String description = statusCode + " from " + httpMethod + " " + uri + " [DefaultWebClient]";
719-
return result.checkpoint(description);
725+
if (StringUtils.hasText(uri.getQuery())) {
726+
try {
727+
uri = new URI(uri.getScheme(), uri.getHost(), uri.getPath(), null);
728+
}
729+
catch (URISyntaxException ex) {
730+
// ignore
731+
}
732+
}
733+
return uri;
720734
}
721735

722736

spring-webflux/src/main/java/org/springframework/web/reactive/socket/adapter/AbstractWebSocketSession.java

Lines changed: 5 additions & 2 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-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.
@@ -73,9 +73,12 @@ protected AbstractWebSocketSession(T delegate, String id, HandshakeInfo info, Da
7373
this.id = id;
7474
this.handshakeInfo = info;
7575
this.bufferFactory = bufferFactory;
76-
this.attributes.putAll(info.getAttributes());
7776
this.logPrefix = initLogPrefix(info, id);
7877

78+
info.getAttributes().entrySet().stream()
79+
.filter(entry -> (entry.getKey() != null && entry.getValue() != null))
80+
.forEach(entry -> this.attributes.put(entry.getKey(), entry.getValue()));
81+
7982
if (logger.isDebugEnabled()) {
8083
logger.debug(getLogPrefix() + "Session id \"" + getId() + "\" for " + getHandshakeInfo().getUri());
8184
}

spring-websocket/src/main/java/org/springframework/web/socket/adapter/AbstractWebSocketSession.java

Lines changed: 4 additions & 2 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-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.
@@ -62,7 +62,9 @@ public abstract class AbstractWebSocketSession<T> implements NativeWebSocketSess
6262
*/
6363
public AbstractWebSocketSession(@Nullable Map<String, Object> attributes) {
6464
if (attributes != null) {
65-
this.attributes.putAll(attributes);
65+
attributes.entrySet().stream()
66+
.filter(entry -> (entry.getKey() != null && entry.getValue() != null))
67+
.forEach(entry -> this.attributes.put(entry.getKey(), entry.getValue()));
6668
}
6769
}
6870

spring-websocket/src/test/java/org/springframework/web/socket/adapter/standard/StandardWebSocketSessionTests.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-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.
@@ -36,6 +36,7 @@
3636
*
3737
* @author Rossen Stoyanchev
3838
*/
39+
@SuppressWarnings("resource")
3940
public class StandardWebSocketSessionTests {
4041

4142
private final HttpHeaders headers = new HttpHeaders();
@@ -53,7 +54,6 @@ public void getPrincipalWithConstructorArg() {
5354
}
5455

5556
@Test
56-
@SuppressWarnings("resource")
5757
public void getPrincipalWithNativeSession() {
5858
TestPrincipal user = new TestPrincipal("joe");
5959

@@ -67,7 +67,6 @@ public void getPrincipalWithNativeSession() {
6767
}
6868

6969
@Test
70-
@SuppressWarnings("resource")
7170
public void getPrincipalNone() {
7271
Session nativeSession = Mockito.mock(Session.class);
7372
given(nativeSession.getUserPrincipal()).willReturn(null);
@@ -82,7 +81,6 @@ public void getPrincipalNone() {
8281
}
8382

8483
@Test
85-
@SuppressWarnings("resource")
8684
public void getAcceptedProtocol() {
8785
String protocol = "foo";
8886

@@ -98,4 +96,14 @@ public void getAcceptedProtocol() {
9896
verifyNoMoreInteractions(nativeSession);
9997
}
10098

99+
@Test // gh-29315
100+
public void addAttributesWithNullKeyOrValue() {
101+
this.attributes.put(null, "value");
102+
this.attributes.put("key", null);
103+
this.attributes.put("foo", "bar");
104+
105+
assertThat(new StandardWebSocketSession(this.headers, this.attributes, null, null).getAttributes())
106+
.hasSize(1).containsEntry("foo", "bar");
107+
}
108+
101109
}

0 commit comments

Comments
 (0)