Consistent use of @Nullable across the codebase (even for internals)
Beyond just formally declaring the current behavior, this revision actually enforces non-null behavior in selected signatures now, not tolerating null values anymore when not explicitly documented. It also changes some utility methods with historic null-in/null-out tolerance towards enforced non-null return values, making them a proper citizen in non-null assignments. Some issues are left as to-do: in particular a thorough revision of spring-test, and a few tests with unclear failures (ignored as "TODO: NULLABLE") to be sorted out in a follow-up commit. Issue: SPR-15540
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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,8 +37,9 @@ public class MockHttpInputMessage implements HttpInputMessage {
|
||||
private final InputStream body;
|
||||
|
||||
|
||||
public MockHttpInputMessage(byte[] contents) {
|
||||
this.body = (contents != null ? new ByteArrayInputStream(contents) : null);
|
||||
public MockHttpInputMessage(byte[] content) {
|
||||
Assert.notNull(content, "Byte array must not be null");
|
||||
this.body = new ByteArrayInputStream(content);
|
||||
}
|
||||
|
||||
public MockHttpInputMessage(InputStream body) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.mock.http;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@@ -77,13 +76,7 @@ public class MockHttpOutputMessage implements HttpOutputMessage {
|
||||
*/
|
||||
public String getBodyAsString(Charset charset) {
|
||||
byte[] bytes = getBodyAsBytes();
|
||||
try {
|
||||
return new String(bytes, charset.name());
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
// should not occur
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -61,6 +62,7 @@ public class DefaultRequestExpectation implements RequestExpectation {
|
||||
return this.requestMatchers;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ResponseCreator getResponseCreator() {
|
||||
return this.responseCreator;
|
||||
}
|
||||
@@ -86,7 +88,7 @@ public class DefaultRequestExpectation implements RequestExpectation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
|
||||
public ClientHttpResponse createResponse(@Nullable ClientHttpRequest request) throws IOException {
|
||||
ResponseCreator responseCreator = getResponseCreator();
|
||||
Assert.state(responseCreator != null, "createResponse() called before ResponseCreator was set");
|
||||
getRequestCount().incrementAndValidate();
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.web.client.response.MockRestResponseCreators;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,6 @@ public interface ResponseCreator {
|
||||
* Create a response for the given request.
|
||||
* @param request the request
|
||||
*/
|
||||
ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException;
|
||||
ClientHttpResponse createResponse(@Nullable ClientHttpRequest request) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -27,6 +27,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mock.http.client.MockClientHttpResponse;
|
||||
import org.springframework.test.web.client.ResponseCreator;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -41,7 +42,7 @@ public class DefaultResponseCreator implements ResponseCreator {
|
||||
|
||||
private HttpStatus statusCode;
|
||||
|
||||
private byte[] content;
|
||||
private byte[] content = new byte[0];
|
||||
|
||||
private Resource contentResource;
|
||||
|
||||
@@ -86,9 +87,7 @@ public class DefaultResponseCreator implements ResponseCreator {
|
||||
* Set the {@code Content-Type} header.
|
||||
*/
|
||||
public DefaultResponseCreator contentType(MediaType mediaType) {
|
||||
if (mediaType != null) {
|
||||
this.headers.setContentType(mediaType);
|
||||
}
|
||||
this.headers.setContentType(mediaType);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -104,17 +103,13 @@ public class DefaultResponseCreator implements ResponseCreator {
|
||||
* Copy all given headers.
|
||||
*/
|
||||
public DefaultResponseCreator headers(HttpHeaders headers) {
|
||||
for (String headerName : headers.keySet()) {
|
||||
for (String headerValue : headers.get(headerName)) {
|
||||
this.headers.add(headerName, headerValue);
|
||||
}
|
||||
}
|
||||
this.headers.putAll(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse createResponse(ClientHttpRequest request) throws IOException {
|
||||
public ClientHttpResponse createResponse(@Nullable ClientHttpRequest request) throws IOException {
|
||||
MockClientHttpResponse response;
|
||||
if (this.contentResource != null) {
|
||||
InputStream stream = this.contentResource.getInputStream();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.client.response;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -44,28 +45,31 @@ public abstract class MockRestResponseCreators {
|
||||
/**
|
||||
* {@code ResponseCreator} for a 200 response (OK) with String body.
|
||||
* @param body the response body, a "UTF-8" string
|
||||
* @param mediaType the type of the content, may be {@code null}
|
||||
* @param contentType the type of the content (may be {@code null})
|
||||
*/
|
||||
public static DefaultResponseCreator withSuccess(String body, @Nullable MediaType mediaType) {
|
||||
return new DefaultResponseCreator(HttpStatus.OK).body(body).contentType(mediaType);
|
||||
public static DefaultResponseCreator withSuccess(String body, @Nullable MediaType contentType) {
|
||||
DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).body(body);
|
||||
return (contentType != null ? creator.contentType(contentType) : creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code ResponseCreator} for a 200 response (OK) with byte[] body.
|
||||
* @param body the response body
|
||||
* @param contentType the type of the content, may be {@code null}
|
||||
* @param contentType the type of the content (may be {@code null})
|
||||
*/
|
||||
public static DefaultResponseCreator withSuccess(byte[] body, @Nullable MediaType contentType) {
|
||||
return new DefaultResponseCreator(HttpStatus.OK).body(body).contentType(contentType);
|
||||
DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).body(body);
|
||||
return (contentType != null ? creator.contentType(contentType) : creator);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code ResponseCreator} for a 200 response (OK) content with {@link Resource}-based body.
|
||||
* @param body the response body
|
||||
* @param contentType the type of the content, may be {@code null}
|
||||
* @param contentType the type of the content (may be {@code null})
|
||||
*/
|
||||
public static DefaultResponseCreator withSuccess(Resource body, @Nullable MediaType contentType) {
|
||||
return new DefaultResponseCreator(HttpStatus.OK).body(body).contentType(contentType);
|
||||
DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).body(body);
|
||||
return (contentType != null ? creator.contentType(contentType) : creator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -496,16 +495,11 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
||||
|
||||
public StaticStringValueResolver(final Map<String, String> values) {
|
||||
this.helper = new PropertyPlaceholderHelper("${", "}", ":", false);
|
||||
this.resolver = new PlaceholderResolver() {
|
||||
@Override
|
||||
public String resolvePlaceholder(String placeholderName) {
|
||||
return values.get(placeholderName);
|
||||
}
|
||||
};
|
||||
this.resolver = values::get;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveStringValue(@Nullable String strVal) throws BeansException {
|
||||
public String resolveStringValue(String strVal) throws BeansException {
|
||||
return this.helper.replacePlaceholders(strVal, this.resolver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -141,13 +141,12 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||
this.beanFactory.addBean(name, bean);
|
||||
}
|
||||
|
||||
public void addBeans(List<?> beans) {
|
||||
if (beans == null) {
|
||||
return;
|
||||
}
|
||||
for (Object bean : beans) {
|
||||
String name = bean.getClass().getName() + "#" + ObjectUtils.getIdentityHexString(bean);
|
||||
this.beanFactory.addBean(name, bean);
|
||||
public void addBeans(@Nullable List<?> beans) {
|
||||
if (beans != null) {
|
||||
for (Object bean : beans) {
|
||||
String name = bean.getClass().getName() + "#" + ObjectUtils.getIdentityHexString(bean);
|
||||
this.beanFactory.addBean(name, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,13 +166,13 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBean(Class<T> requiredType) throws BeansException {
|
||||
return this.beanFactory.getBean(requiredType);
|
||||
public Object getBean(String name, Object... args) throws BeansException {
|
||||
return this.beanFactory.getBean(name, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBean(String name, Object... args) throws BeansException {
|
||||
return this.beanFactory.getBean(name, args);
|
||||
public <T> T getBean(Class<T> requiredType) throws BeansException {
|
||||
return this.beanFactory.getBean(requiredType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -202,7 +201,7 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
|
||||
public boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
|
||||
return this.beanFactory.isTypeMatch(name, typeToMatch);
|
||||
}
|
||||
|
||||
@@ -405,7 +404,7 @@ class StubWebApplicationContext implements WebApplicationContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
|
||||
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
|
||||
throw new UnsupportedOperationException("Dependency resolution not supported");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user