Forbid null converters in RestTemplate & HttpMessageConverterExtractor

Prior to this commit, RestTemplate and HttpMessageConverterExtractor did
not validate that the supplied HttpMessageConverter list contained no
null elements, which can lead to a NullPointerException when the
converters are accessed.

This commit improves the user experience by failing immediately if the
supplied HttpMessageConverter list contains a null element. This applies
to constructors for RestTemplate and HttpMessageConverterExtractor as
well as to RestTemplate#setMessageConverters().

Note, however, that RestTemplate#getMessageConverters() returns a mutable
list. Thus, if a user modifies that list so that it contains null values,
that will still lead to a NullPointerException when the converters are
accessed.

This commit also introduces noNullElements() variants for collections in
org.springframework.util.Assert.

Closes gh-23151
This commit is contained in:
Sam Brannen
2019-06-18 15:56:50 +03:00
parent 8ceac9c015
commit 4000b244ff
5 changed files with 102 additions and 61 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@@ -37,6 +37,7 @@ import org.springframework.util.Assert;
* to convert the response into a type {@code T}.
*
* @author Arjen Poutsma
* @author Sam Brannen
* @since 3.0
* @param <T> the data type
* @see RestTemplate
@@ -73,6 +74,7 @@ public class HttpMessageConverterExtractor<T> implements ResponseExtractor<T> {
HttpMessageConverterExtractor(Type responseType, List<HttpMessageConverter<?>> messageConverters, Log logger) {
Assert.notNull(responseType, "'responseType' must not be null");
Assert.notEmpty(messageConverters, "'messageConverters' must not be empty");
Assert.noNullElements(messageConverters, "'messageConverters' must not contain null elements");
this.responseType = responseType;
this.responseClass = (responseType instanceof Class ? (Class<T>) responseType : null);
this.messageConverters = messageConverters;

View File

@@ -84,6 +84,7 @@ import org.springframework.web.util.UriTemplateHandler;
* @author Brian Clozel
* @author Roy Clarkson
* @author Juergen Hoeller
* @author Sam Brannen
* @since 3.0
* @see HttpMessageConverter
* @see RequestCallback
@@ -198,11 +199,12 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
* @since 3.2.7
*/
public RestTemplate(List<HttpMessageConverter<?>> messageConverters) {
Assert.notEmpty(messageConverters, "At least one HttpMessageConverter required");
validateConverters(messageConverters);
this.messageConverters.addAll(messageConverters);
this.uriTemplateHandler = initUriTemplateHandler();
}
private static DefaultUriBuilderFactory initUriTemplateHandler() {
DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
uriFactory.setEncodingMode(EncodingMode.URI_COMPONENT); // for backwards compatibility..
@@ -215,7 +217,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
* <p>These converters are used to convert from and to HTTP requests and responses.
*/
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
Assert.notEmpty(messageConverters, "At least one HttpMessageConverter required");
validateConverters(messageConverters);
// Take getMessageConverters() List as-is when passed in here
if (this.messageConverters != messageConverters) {
this.messageConverters.clear();
@@ -223,6 +225,11 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
}
}
private void validateConverters(List<HttpMessageConverter<?>> messageConverters) {
Assert.notEmpty(messageConverters, "At least one HttpMessageConverter is required");
Assert.noNullElements(messageConverters, "The HttpMessageConverter list must not contain null elements");
}
/**
* Return the list of message body converters.
* <p>The returned {@link List} is active and may get appended to.