Nullability fine-tuning around declaration inconsistencies

Issue: SPR-15720
Issue: SPR-15792
This commit is contained in:
Juergen Hoeller
2017-07-19 22:22:14 +02:00
parent 68e6b148cb
commit 46eba3dbfa
186 changed files with 986 additions and 619 deletions

View File

@@ -36,8 +36,10 @@ public final class ResponseCookie extends HttpCookie {
private final Duration maxAge;
@Nullable
private final String domain;
@Nullable
private final String path;
private final boolean secure;
@@ -48,8 +50,8 @@ public final class ResponseCookie extends HttpCookie {
/**
* Private constructor. See {@link #from(String, String)}.
*/
private ResponseCookie(String name, String value, Duration maxAge, String domain,
String path, boolean secure, boolean httpOnly) {
private ResponseCookie(String name, String value, Duration maxAge, @Nullable String domain,
@Nullable String path, boolean secure, boolean httpOnly) {
super(name, value);
Assert.notNull(maxAge, "Max age must not be null");
@@ -168,8 +170,10 @@ public final class ResponseCookie extends HttpCookie {
private Duration maxAge = Duration.ofSeconds(-1);
@Nullable
private String domain;
@Nullable
private String path;
private boolean secure;

View File

@@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -44,14 +45,16 @@ public class AsyncHttpAccessor {
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private org.springframework.http.client.AsyncClientHttpRequestFactory asyncRequestFactory;
/**
* Set the request factory that this accessor uses for obtaining {@link
* org.springframework.http.client.ClientHttpRequest HttpRequests}.
*/
public void setAsyncRequestFactory(org.springframework.http.client.AsyncClientHttpRequestFactory asyncRequestFactory) {
Assert.notNull(asyncRequestFactory, "'asyncRequestFactory' must not be null");
Assert.notNull(asyncRequestFactory, "AsyncClientHttpRequestFactory must not be null");
this.asyncRequestFactory = asyncRequestFactory;
}
@@ -60,6 +63,7 @@ public class AsyncHttpAccessor {
* org.springframework.http.client.ClientHttpRequest HttpRequests}.
*/
public org.springframework.http.client.AsyncClientHttpRequestFactory getAsyncRequestFactory() {
Assert.state(asyncRequestFactory != null, "No AsyncClientHttpRequestFactory set");
return this.asyncRequestFactory;
}
@@ -73,7 +77,9 @@ public class AsyncHttpAccessor {
*/
protected org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest(URI url, HttpMethod method)
throws IOException {
org.springframework.http.client.AsyncClientHttpRequest request = getAsyncRequestFactory().createAsyncRequest(url, method);
org.springframework.http.client.AsyncClientHttpRequest request =
getAsyncRequestFactory().createAsyncRequest(url, method);
if (logger.isDebugEnabled()) {
logger.debug("Created asynchronous " + method.name() + " request for \"" + url + "\"");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 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.
@@ -22,6 +22,7 @@ import java.net.SocketAddress;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -36,10 +37,12 @@ public class ProxyFactoryBean implements FactoryBean<Proxy>, InitializingBean {
private Proxy.Type type = Proxy.Type.HTTP;
@Nullable
private String hostname;
private int port = -1;
@Nullable
private Proxy proxy;
@@ -68,10 +71,10 @@ public class ProxyFactoryBean implements FactoryBean<Proxy>, InitializingBean {
@Override
public void afterPropertiesSet() throws IllegalArgumentException {
Assert.notNull(this.type, "'type' must not be null");
Assert.hasLength(this.hostname, "'hostname' must not be empty");
Assert.notNull(this.type, "Property 'type' is required");
Assert.notNull(this.hostname, "Property 'hostname' is required");
if (this.port < 0 || this.port > 65535) {
throw new IllegalArgumentException("'port' value out of range: " + this.port);
throw new IllegalArgumentException("Property 'port' value out of range: " + this.port);
}
SocketAddress socketAddress = new InetSocketAddress(this.hostname, this.port);

View File

@@ -198,6 +198,7 @@ public class Jaxb2XmlDecoder extends AbstractDecoder<Object> {
private final QName desiredName;
@Nullable
private List<XMLEvent> events;
private int elementDepth = 0;

View File

@@ -52,7 +52,7 @@ public class GsonHttpMessageConverter extends AbstractJsonHttpMessageConverter {
* Construct a new {@code GsonHttpMessageConverter} with default configuration.
*/
public GsonHttpMessageConverter() {
this(new Gson());
this.gson = new Gson();
}
/**
@@ -61,7 +61,8 @@ public class GsonHttpMessageConverter extends AbstractJsonHttpMessageConverter {
* @since 5.0
*/
public GsonHttpMessageConverter(Gson gson) {
setGson(gson);
Assert.notNull(gson, "A Gson instance is required");
this.gson = gson;
}

View File

@@ -58,7 +58,7 @@ public class JsonbHttpMessageConverter extends AbstractJsonHttpMessageConverter
* @param config the {@code JsonbConfig} for the underlying delegate
*/
public JsonbHttpMessageConverter(JsonbConfig config) {
this(JsonbBuilder.create(config));
this.jsonb = JsonbBuilder.create(config);
}
/**
@@ -66,7 +66,8 @@ public class JsonbHttpMessageConverter extends AbstractJsonHttpMessageConverter
* @param jsonb the Jsonb instance to use
*/
public JsonbHttpMessageConverter(Jsonb jsonb) {
setJsonb(jsonb);
Assert.notNull(jsonb, "A Jsonb instance is required");
this.jsonb = jsonb;
}

View File

@@ -59,7 +59,7 @@ public abstract class AbstractServerHttpRequest implements ServerHttpRequest {
* @param contextPath the context path for the request
* @param headers the headers for the request
*/
public AbstractServerHttpRequest(URI uri, String contextPath, HttpHeaders headers) {
public AbstractServerHttpRequest(URI uri, @Nullable String contextPath, HttpHeaders headers) {
this.uri = uri;
this.path = RequestPath.parse(uri, contextPath);
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);

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.
@@ -18,6 +18,7 @@ package org.springframework.remoting.caucho;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
/**
* {@link FactoryBean} for Hessian proxies. Exposes the proxied service
@@ -42,6 +43,7 @@ import org.springframework.beans.factory.FactoryBean;
*/
public class HessianProxyFactoryBean extends HessianClientInterceptor implements FactoryBean<Object> {
@Nullable
private Object serviceProxy;

View File

@@ -76,6 +76,7 @@ public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerR
private boolean acceptGzipEncoding = true;
@Nullable
private ClassLoader beanClassLoader;
@@ -121,6 +122,7 @@ public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerR
/**
* Return the bean ClassLoader that this executor is supposed to use.
*/
@Nullable
protected ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}

View File

@@ -18,6 +18,7 @@ package org.springframework.remoting.httpinvoker;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -55,6 +56,7 @@ import org.springframework.util.Assert;
*/
public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean<Object> {
@Nullable
private Object serviceProxy;

View File

@@ -20,6 +20,7 @@ import javax.xml.ws.BindingProvider;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -34,6 +35,7 @@ import org.springframework.util.Assert;
*/
public class JaxWsPortProxyFactoryBean extends JaxWsPortClientInterceptor implements FactoryBean<Object> {
@Nullable
private Object serviceProxy;

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.
@@ -29,6 +29,7 @@ import org.springframework.lang.Nullable;
@SuppressWarnings("serial")
public class HttpSessionRequiredException extends ServletException {
@Nullable
private String expectedAttribute;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 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.
@@ -36,7 +36,7 @@ public interface SessionAttributeStore {
* @param attributeName the name of the attribute
* @param attributeValue the attribute value to store
*/
void storeAttribute(WebRequest request, String attributeName, @Nullable Object attributeValue);
void storeAttribute(WebRequest request, String attributeName, Object attributeValue);
/**
* Retrieve the specified attribute from the backend session.

View File

@@ -17,21 +17,21 @@
package org.springframework.web.client;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
* Implementation of {@link ResponseErrorHandler} that uses {@link HttpMessageConverter}s to
* convert HTTP error responses to {@link RestClientException}.
*
* <p>To use this error handler, you must specify a
* {@linkplain #setStatusMapping(Map) status mapping} and/or a
* {@linkplain #setSeriesMapping(Map) series mapping}. If either of these mappings has a match
@@ -42,6 +42,7 @@ import org.springframework.util.CollectionUtils;
* into the mapped subclass of {@link RestClientException}. Note that the
* {@linkplain #setStatusMapping(Map) status mapping} takes precedence over
* {@linkplain #setSeriesMapping(Map) series mapping}.
*
* <p>If there is no match, this error handler will default to the behavior of
* {@link DefaultResponseErrorHandler}. Note that you can override this default behavior by
* specifying a {@linkplain #setSeriesMapping(Map) series mapping} from
@@ -50,19 +51,17 @@ import org.springframework.util.CollectionUtils;
*
* @author Simon Galperin
* @author Arjen Poutsma
* @see RestTemplate#setErrorHandler(ResponseErrorHandler)
* @since 5.0
* @see RestTemplate#setErrorHandler(ResponseErrorHandler)
*/
public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
implements InitializingBean {
public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler {
private List<HttpMessageConverter<?>> messageConverters;
private List<HttpMessageConverter<?>> messageConverters = Collections.emptyList();
private final Map<HttpStatus, Class<? extends RestClientException>> statusMapping =
new LinkedHashMap<>();
private final Map<HttpStatus, Class<? extends RestClientException>> statusMapping = new LinkedHashMap<>();
private final Map<HttpStatus.Series, Class<? extends RestClientException>> seriesMapping = new LinkedHashMap<>();
private final Map<HttpStatus.Series, Class<? extends RestClientException>> seriesMapping =
new LinkedHashMap<>();
/**
* Create a new, empty {@code ExtractingResponseErrorHandler}.
@@ -77,11 +76,12 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
* @param messageConverters the message converters to use
*/
public ExtractingResponseErrorHandler(List<HttpMessageConverter<?>> messageConverters) {
setMessageConverters(messageConverters);
this.messageConverters = messageConverters;
}
/**
* Sets the message converters to use by this extractor.
* Set the message converters to use by this extractor.
*/
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
@@ -96,8 +96,7 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
* {@linkplain #setMessageConverters(List) configured message converters} to convert the
* response into the mapped subclass of {@link RestClientException}.
*/
public void setStatusMapping(
Map<HttpStatus, Class<? extends RestClientException>> statusMapping) {
public void setStatusMapping(Map<HttpStatus, Class<? extends RestClientException>> statusMapping) {
if (!CollectionUtils.isEmpty(statusMapping)) {
this.statusMapping.putAll(statusMapping);
}
@@ -112,17 +111,12 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
* {@linkplain #setMessageConverters(List) configured message converters} to convert the
* response into the mapped subclass of {@link RestClientException}.
*/
public void setSeriesMapping(
Map<HttpStatus.Series, Class<? extends RestClientException>> seriesMapping) {
public void setSeriesMapping(Map<HttpStatus.Series, Class<? extends RestClientException>> seriesMapping) {
if (!CollectionUtils.isEmpty(seriesMapping)) {
this.seriesMapping.putAll(seriesMapping);
}
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(this.messageConverters, "'messageConverters' is required");
}
@Override
protected boolean hasError(HttpStatus statusCode) {
@@ -157,6 +151,7 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
if (exceptionClass == null) {
return;
}
HttpMessageConverterExtractor<? extends RestClientException> extractor =
new HttpMessageConverterExtractor<>(exceptionClass, this.messageConverters);
RestClientException exception = extractor.extractData(response);
@@ -164,4 +159,5 @@ public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler
throw exception;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 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.
@@ -23,6 +23,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.HttpRequestMethodNotSupportedException;
@@ -48,6 +50,7 @@ import org.springframework.web.context.WebApplicationContext;
@SuppressWarnings("serial")
public class HttpRequestHandlerServlet extends HttpServlet {
@Nullable
private HttpRequestHandler target;
@@ -62,6 +65,8 @@ public class HttpRequestHandlerServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Assert.state(this.target != null, "No HttpRequestHandler available");
LocaleContextHolder.setLocale(request.getLocale());
try {
this.target.handleRequest(request, response);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 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.
@@ -23,6 +23,8 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.support.LiveBeansView;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Servlet variant of {@link LiveBeansView}'s MBean exposure.
@@ -37,8 +39,10 @@ import org.springframework.context.support.LiveBeansView;
@SuppressWarnings("serial")
public class LiveBeansViewServlet extends HttpServlet {
@Nullable
private LiveBeansView liveBeansView;
@Override
public void init() throws ServletException {
this.liveBeansView = buildLiveBeansView();
@@ -48,8 +52,12 @@ public class LiveBeansViewServlet extends HttpServlet {
return new ServletContextLiveBeansView(getServletContext());
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Assert.state(this.liveBeansView != null, "No LiveBeanViews available");
String content = this.liveBeansView.getSnapshotAsJson();
response.setContentType("application/json");
response.setContentLength(content.length());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 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.
@@ -22,6 +22,7 @@ import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.context.ServletContextAware;
/**
@@ -48,6 +49,7 @@ public class ServletContextAttributeExporter implements ServletContextAware {
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private Map<String, Object> attributes;
@@ -65,16 +67,18 @@ public class ServletContextAttributeExporter implements ServletContextAware {
@Override
public void setServletContext(ServletContext servletContext) {
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
String attributeName = entry.getKey();
if (logger.isWarnEnabled()) {
if (servletContext.getAttribute(attributeName) != null) {
logger.warn("Replacing existing ServletContext attribute with name '" + attributeName + "'");
if (this.attributes != null) {
for (Map.Entry<String, Object> entry : this.attributes.entrySet()) {
String attributeName = entry.getKey();
if (logger.isWarnEnabled()) {
if (servletContext.getAttribute(attributeName) != null) {
logger.warn("Replacing existing ServletContext attribute with name '" + attributeName + "'");
}
}
servletContext.setAttribute(attributeName, entry.getValue());
if (logger.isInfoEnabled()) {
logger.info("Exported ServletContext attribute with name '" + attributeName + "'");
}
}
servletContext.setAttribute(attributeName, entry.getValue());
if (logger.isInfoEnabled()) {
logger.info("Exported ServletContext attribute with name '" + attributeName + "'");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 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.
@@ -20,6 +20,7 @@ import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.web.context.WebApplicationContext;
/**
@@ -78,6 +79,7 @@ public class DelegatingNavigationHandlerProxy extends NavigationHandler {
*/
public final static String DEFAULT_TARGET_BEAN_NAME = "jsfNavigationHandler";
@Nullable
private NavigationHandler originalNavigationHandler;

View File

@@ -69,10 +69,13 @@ public class HandlerMethod {
private final MethodParameter[] parameters;
@Nullable
private HttpStatus responseStatus;
@Nullable
private String responseStatusReason;
@Nullable
private HandlerMethod resolvedFromHandlerMethod;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 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.
@@ -20,6 +20,7 @@ import java.util.Map;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
@@ -45,9 +46,10 @@ public class MapMethodProcessor implements HandlerMethodArgumentResolver, Handle
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
return mavContainer.getModel();
}
@@ -61,13 +63,10 @@ public class MapMethodProcessor implements HandlerMethodArgumentResolver, Handle
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
if (returnValue == null) {
return;
}
else if (returnValue instanceof Map){
if (returnValue instanceof Map){
mavContainer.addAllAttributes((Map) returnValue);
}
else {
else if (returnValue != null) {
// should not happen
throw new UnsupportedOperationException("Unexpected return type: " +
returnType.getParameterType().getName() + " in method: " + returnType.getMethod());

View File

@@ -215,7 +215,7 @@ public final class ModelFactory {
List<String> keyNames = new ArrayList<>(model.keySet());
for (String name : keyNames) {
Object value = model.get(name);
if (isBindingCandidate(name, value)) {
if (value != null && isBindingCandidate(name, value)) {
String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + name;
if (!model.containsAttribute(bindingResultKey)) {
WebDataBinder dataBinder = this.dataBinderFactory.createBinder(request, value, name);
@@ -228,17 +228,16 @@ public final class ModelFactory {
/**
* Whether the given attribute requires a {@link BindingResult} in the model.
*/
private boolean isBindingCandidate(String attributeName, @Nullable Object value) {
private boolean isBindingCandidate(String attributeName, Object value) {
if (attributeName.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
return false;
}
Class<?> attrType = (value != null ? value.getClass() : null);
if (this.sessionAttributesHandler.isHandlerSessionAttribute(attributeName, attrType)) {
if (this.sessionAttributesHandler.isHandlerSessionAttribute(attributeName, value.getClass())) {
return true;
}
return (value != null && !value.getClass().isArray() && !(value instanceof Collection) &&
return (!value.getClass().isArray() && !(value instanceof Collection) &&
!(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass()));
}

View File

@@ -19,6 +19,7 @@ package org.springframework.web.method.annotation;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
@@ -44,9 +45,10 @@ public class ModelMethodProcessor implements HandlerMethodArgumentResolver, Hand
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
return mavContainer.getModel();
}

View File

@@ -85,21 +85,19 @@ public class SessionAttributesHandler {
* session attributes through an {@link SessionAttributes} annotation.
*/
public boolean hasSessionAttributes() {
return (this.attributeNames.size() > 0 || this.attributeTypes.size() > 0);
return (!this.attributeNames.isEmpty() || !this.attributeTypes.isEmpty());
}
/**
* Whether the attribute name or type match the names and types specified
* via {@code @SessionAttributes} in underlying controller.
*
* <p>Attributes successfully resolved through this method are "remembered"
* and subsequently used in {@link #retrieveAttributes(WebRequest)} and
* {@link #cleanupAttributes(WebRequest)}.
*
* @param attributeName the attribute name to check, never {@code null}
* @param attributeType the type for the attribute, possibly {@code null}
* @param attributeName the attribute name to check
* @param attributeType the type for the attribute
*/
public boolean isHandlerSessionAttribute(String attributeName, @Nullable Class<?> attributeType) {
public boolean isHandlerSessionAttribute(String attributeName, Class<?> attributeType) {
Assert.notNull(attributeName, "Attribute name must not be null");
if (this.attributeNames.contains(attributeName) || this.attributeTypes.contains(attributeType)) {
this.knownAttributeNames.add(attributeName);
@@ -119,8 +117,7 @@ public class SessionAttributesHandler {
public void storeAttributes(WebRequest request, Map<String, ?> attributes) {
for (String name : attributes.keySet()) {
Object value = attributes.get(name);
Class<?> attrType = (value != null ? value.getClass() : null);
if (isHandlerSessionAttribute(name, attrType)) {
if (value != null && isHandlerSessionAttribute(name, value.getClass())) {
this.sessionAttributeStore.storeAttribute(request, name, value);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 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.
@@ -17,6 +17,8 @@
package org.springframework.web.method.annotation;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
@@ -38,9 +40,10 @@ public class SessionStatusMethodArgumentResolver implements HandlerMethodArgumen
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAndViewContainer is required for session status exposure");
return mavContainer.getSessionStatus();
}

View File

@@ -105,7 +105,6 @@ public class WebHttpHandlerBuilder {
* Copy constructor.
*/
private WebHttpHandlerBuilder(WebHttpHandlerBuilder other) {
this.webHandler = other.webHandler;
this.filters.addAll(other.filters);
this.exceptionHandlers.addAll(other.exceptionHandlers);
@@ -128,24 +127,23 @@ public class WebHttpHandlerBuilder {
* Static factory method to create a new builder instance by detecting beans
* in an {@link ApplicationContext}. The following are detected:
* <ul>
* <li>{@link WebHandler} [1] -- looked up by the name
* {@link #WEB_HANDLER_BEAN_NAME}.
* <li>{@link WebFilter} [0..N] -- detected by type and ordered,
* see {@link AnnotationAwareOrderComparator}.
* <li>{@link WebExceptionHandler} [0..N] -- detected by type and
* ordered.
* <li>{@link WebSessionManager} [0..1] -- looked up by the name
* {@link #WEB_SESSION_MANAGER_BEAN_NAME}.
* <li>{@link ServerCodecConfigurer} [0..1] -- looked up by the name
* {@link #SERVER_CODEC_CONFIGURER_BEAN_NAME}.
*<li>{@link LocaleContextResolver} [0..1] -- looked up by the name
* {@link #LOCALE_CONTEXT_RESOLVER_BEAN_NAME}.
* <li>{@link WebHandler} [1] -- looked up by the name
* {@link #WEB_HANDLER_BEAN_NAME}.
* <li>{@link WebFilter} [0..N] -- detected by type and ordered,
* see {@link AnnotationAwareOrderComparator}.
* <li>{@link WebExceptionHandler} [0..N] -- detected by type and
* ordered.
* <li>{@link WebSessionManager} [0..1] -- looked up by the name
* {@link #WEB_SESSION_MANAGER_BEAN_NAME}.
* <li>{@link ServerCodecConfigurer} [0..1] -- looked up by the name
* {@link #SERVER_CODEC_CONFIGURER_BEAN_NAME}.
* <li>{@link LocaleContextResolver} [0..1] -- looked up by the name
* {@link #LOCALE_CONTEXT_RESOLVER_BEAN_NAME}.
* </ul>
* @param context the application context to use for the lookup
* @return the prepared builder
*/
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder(
context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class));
@@ -297,7 +295,6 @@ public class WebHttpHandlerBuilder {
private List<WebExceptionHandler> exceptionHandlers = Collections.emptyList();
@Autowired(required = false)
public void setFilters(List<WebFilter> filters) {
this.filters = filters;