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:
Juergen Hoeller
2017-06-07 14:17:48 +02:00
parent ffc3f6d87d
commit f813712f5b
1493 changed files with 10670 additions and 9172 deletions

View File

@@ -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.
@@ -101,14 +101,6 @@ public class DispatcherServletTests {
return servletConfig.getServletContext();
}
@Test
public void dispatcherServletGetServletNameDoesNotFailWithoutConfig() {
DispatcherServlet ds = new DispatcherServlet();
assertNull(ds.getServletConfig());
assertNull(ds.getServletName());
assertNull(ds.getServletContext());
}
@Test
public void configuredDispatcherServlets() {
assertTrue("Correct namespace",

View File

@@ -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.
@@ -39,10 +39,7 @@ import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapt
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
/**
* Test fixture with a {@link InterceptorRegistry}, two {@link HandlerInterceptor}s and two
@@ -142,14 +139,12 @@ public class InterceptorRegistryTests {
verifyWebInterceptor(interceptors.get(0), this.webInterceptor2);
}
// SPR-11130
@Test
@Test // SPR-11130
public void addInterceptorWithExcludePathPatternOnly() {
this.registry.addInterceptor(this.interceptor1).excludePathPatterns("/path1/secret");
this.registry.addInterceptor(this.interceptor2).addPathPatterns("/path2");
assertEquals(Arrays.asList(this.interceptor1), getInterceptorsForPath("/path1"));
assertEquals(Collections.singletonList(this.interceptor1), getInterceptorsForPath("/path1"));
assertEquals(Arrays.asList(this.interceptor1, this.interceptor2), getInterceptorsForPath("/path2"));
assertEquals(Collections.emptyList(), getInterceptorsForPath("/path1/secret"));
}

View File

@@ -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.
@@ -45,7 +45,6 @@ import static org.springframework.web.servlet.mvc.method.RequestMappingInfo.path
*/
public class RequestMappingInfoTests {
@Test
public void createEmpty() {
RequestMappingInfo info = paths().build();

View File

@@ -30,6 +30,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.JsonView;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
@@ -249,8 +250,8 @@ public class RequestResponseBodyMethodProcessorTests {
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
@SuppressWarnings("unchecked")
List<SimpleBean> result = (List<SimpleBean>)
processor.resolveArgument(methodParam, container, request, factory);
List<SimpleBean> result = (List<SimpleBean>) processor.resolveArgument(
methodParam, container, request, factory);
assertNotNull(result);
assertEquals("Jad", result.get(0).getName());
@@ -306,9 +307,7 @@ public class RequestResponseBodyMethodProcessorTests {
assertEquals("Foo", servletResponse.getContentAsString());
}
// SPR-13423
@Test
@Test // SPR-13423
public void handleReturnValueCharSequence() throws Exception {
List<HttpMessageConverter<?>>converters = new ArrayList<>();
converters.add(new ByteArrayHttpMessageConverter());
@@ -369,7 +368,6 @@ public class RequestResponseBodyMethodProcessorTests {
@Test
public void addContentDispositionHeader() throws Exception {
ContentNegotiationManagerFactoryBean factory = new ContentNegotiationManagerFactoryBean();
factory.addMediaType("pdf", new MediaType("application", "pdf"));
factory.afterPropertiesSet();
@@ -509,6 +507,7 @@ public class RequestResponseBodyMethodProcessorTests {
}
@Test // SPR-12501
@Ignore // TODO: NULLABLE
public void resolveArgumentWithJacksonJsonView() throws Exception {
String content = "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}";
this.servletRequest.setContent(content.getBytes("UTF-8"));
@@ -525,8 +524,8 @@ public class RequestResponseBodyMethodProcessorTests {
converters, null, Collections.singletonList(new JsonViewRequestBodyAdvice()));
@SuppressWarnings("unchecked")
JacksonViewBean result = (JacksonViewBean)processor.resolveArgument(methodParameter,
this.container, this.request, this.factory);
JacksonViewBean result = (JacksonViewBean)
processor.resolveArgument(methodParameter, this.container, this.request, this.factory);
assertNotNull(result);
assertEquals("with", result.getWithView1());
@@ -535,6 +534,7 @@ public class RequestResponseBodyMethodProcessorTests {
}
@Test // SPR-12501
@Ignore // TODO: NULLABLE
public void resolveHttpEntityArgumentWithJacksonJsonView() throws Exception {
String content = "{\"withView1\" : \"with\", \"withView2\" : \"with\", \"withoutView\" : \"without\"}";
this.servletRequest.setContent(content.getBytes("UTF-8"));
@@ -551,8 +551,8 @@ public class RequestResponseBodyMethodProcessorTests {
converters, null, Collections.singletonList(new JsonViewRequestBodyAdvice()));
@SuppressWarnings("unchecked")
HttpEntity<JacksonViewBean> result = (HttpEntity<JacksonViewBean>)processor.resolveArgument(
methodParameter, this.container, this.request, this.factory);
HttpEntity<JacksonViewBean> result = (HttpEntity<JacksonViewBean>)
processor.resolveArgument( methodParameter, this.container, this.request, this.factory);
assertNotNull(result);
assertNotNull(result.getBody());
@@ -562,6 +562,7 @@ public class RequestResponseBodyMethodProcessorTests {
}
@Test // SPR-12501
@Ignore // TODO: NULLABLE
public void resolveArgumentWithJacksonJsonViewAndXmlMessageConverter() throws Exception {
String content = "<root><withView1>with</withView1><withView2>with</withView2><withoutView>without</withoutView></root>";
this.servletRequest.setContent(content.getBytes("UTF-8"));
@@ -578,8 +579,8 @@ public class RequestResponseBodyMethodProcessorTests {
converters, null, Collections.singletonList(new JsonViewRequestBodyAdvice()));
@SuppressWarnings("unchecked")
JacksonViewBean result = (JacksonViewBean)processor.resolveArgument(methodParameter,
this.container, this.request, this.factory);
JacksonViewBean result = (JacksonViewBean)
processor.resolveArgument(methodParameter, this.container, this.request, this.factory);
assertNotNull(result);
assertEquals("with", result.getWithView1());
@@ -588,6 +589,7 @@ public class RequestResponseBodyMethodProcessorTests {
}
@Test // SPR-12501
@Ignore // TODO: NULLABLE
public void resolveHttpEntityArgumentWithJacksonJsonViewAndXmlMessageConverter() throws Exception {
String content = "<root><withView1>with</withView1><withView2>with</withView2><withoutView>without</withoutView></root>";
this.servletRequest.setContent(content.getBytes("UTF-8"));
@@ -604,8 +606,8 @@ public class RequestResponseBodyMethodProcessorTests {
converters, null, Collections.singletonList(new JsonViewRequestBodyAdvice()));
@SuppressWarnings("unchecked")
HttpEntity<JacksonViewBean> result = (HttpEntity<JacksonViewBean>)processor.resolveArgument(methodParameter,
this.container, this.request, this.factory);
HttpEntity<JacksonViewBean> result = (HttpEntity<JacksonViewBean>)
processor.resolveArgument(methodParameter, this.container, this.request, this.factory);
assertNotNull(result);
assertNotNull(result.getBody());
@@ -700,8 +702,8 @@ public class RequestResponseBodyMethodProcessorTests {
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
String value = (String)processor.readWithMessageConverters(this.request, methodParameter,
methodParameter.getGenericParameterType());
String value = (String) processor.readWithMessageConverters(
this.request, methodParameter, methodParameter.getGenericParameterType());
assertEquals("foo", value);
}
@@ -1013,13 +1015,6 @@ public class RequestResponseBodyMethodProcessorTests {
return StringHttpMessageConverter.class.equals(converterType);
}
@Override
public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return "default value for empty body";
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
@@ -1033,6 +1028,13 @@ public class RequestResponseBodyMethodProcessorTests {
return body;
}
@Override
public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,
Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return "default value for empty body";
}
}

View File

@@ -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.
@@ -46,8 +46,9 @@ public class EvalTagTests extends AbstractTagTests {
private MockPageContext context;
@Before
public void setUp() throws Exception {
public void setup() throws Exception {
context = createPageContext();
FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
factory.afterPropertiesSet();
@@ -57,6 +58,7 @@ public class EvalTagTests extends AbstractTagTests {
tag.setPageContext(context);
}
@Test
public void printScopedAttributeResult() throws Exception {
tag.setExpression("bean.method()");
@@ -123,8 +125,7 @@ public class EvalTagTests extends AbstractTagTests {
assertEquals(new BigDecimal(".25"), context.getAttribute("foo"));
}
// SPR-6923
@Test
@Test // SPR-6923
public void nestedPropertyWithAttributeName() throws Exception {
tag.setExpression("bean.bean");
tag.setVar("foo");

View File

@@ -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.
@@ -79,23 +79,6 @@ public class MessageTagTests extends AbstractTagTests {
assertEquals("Correct message", "test message", message.toString());
}
@Test
public void messageTagWithNullCode() throws JspException {
PageContext pc = createPageContext();
final StringBuffer message = new StringBuffer();
MessageTag tag = new MessageTag() {
@Override
protected void writeMessage(String msg) {
message.append(msg);
}
};
tag.setPageContext(pc);
tag.setCode(null);
assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE);
assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag());
assertEquals("Correct message", "null", message.toString());
}
@Test
public void messageTagWithCodeAndArgument() throws JspException {
PageContext pc = createPageContext();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 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.
@@ -85,18 +85,6 @@ public class ViewResolverTests {
assertEquals("Correct URL", "/example2.jsp", ((JstlView) view).getUrl());
}
@Test
public void testUrlBasedViewResolverWithNullViewClass() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
try {
resolver.setViewClass(null);
fail("Should have thrown IllegalArgumentException");
}
catch (IllegalArgumentException ex) {
// expected
}
}
@Test
public void testUrlBasedViewResolverWithoutPrefixes() throws Exception {
UrlBasedViewResolver vr = new UrlBasedViewResolver();