diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java index 54186435878..ec6b9dd95cb 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBean.java @@ -126,7 +126,7 @@ public class FieldRetrievingFactoryBean * @see #setTargetObject */ public void setTargetField(@Nullable String targetField) { - this.targetField = StringUtils.trimAllWhitespace(targetField); + this.targetField = (targetField != null ? StringUtils.trimAllWhitespace(targetField) : null); } /** diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java index d76eeccd854..ad241a16d9e 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java @@ -81,8 +81,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker protected final Log logger = LogFactory.getLog(getClass()); - private final Map metadataCache = - new ConcurrentHashMap<>(1024); + private final Map metadataCache = new ConcurrentHashMap<>(1024); private final CacheOperationExpressionEvaluator evaluator = new CacheOperationExpressionEvaluator(); @@ -186,6 +185,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker public void afterSingletonsInstantiated() { if (getCacheResolver() == null) { // Lazily initialize cache resolver via default cache manager... + Assert.state(this.beanFactory != null, "CacheResolver or BeanFactory must be set on cache aspect"); try { setCacheManager(this.beanFactory.getBean(CacheManager.class)); } @@ -289,6 +289,10 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker * @see CacheOperation#cacheResolver */ protected T getBean(String beanName, Class expectedType) { + if (this.beanFactory == null) { + throw new IllegalStateException( + "BeanFactory must be set on cache aspect for " + expectedType.getSimpleName() + " retrieval"); + } return BeanFactoryAnnotationUtils.qualifiedBeanOfType(this.beanFactory, expectedType, beanName); } diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractResourceBasedMessageSource.java b/spring-context/src/main/java/org/springframework/context/support/AbstractResourceBasedMessageSource.java index d31075a76e9..c5d8e7091fb 100644 --- a/spring-context/src/main/java/org/springframework/context/support/AbstractResourceBasedMessageSource.java +++ b/spring-context/src/main/java/org/springframework/context/support/AbstractResourceBasedMessageSource.java @@ -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. @@ -38,6 +38,7 @@ public abstract class AbstractResourceBasedMessageSource extends AbstractMessage private final Set basenameSet = new LinkedHashSet<>(4); + @Nullable private String defaultEncoding; private boolean fallbackToSystemLocale = true; diff --git a/spring-context/src/main/java/org/springframework/validation/DataBinder.java b/spring-context/src/main/java/org/springframework/validation/DataBinder.java index 062dbed7769..9367f21aa2e 100644 --- a/spring-context/src/main/java/org/springframework/validation/DataBinder.java +++ b/spring-context/src/main/java/org/springframework/validation/DataBinder.java @@ -535,9 +535,6 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter { } private void assertValidators(Validator... validators) { - if (validators == null) { - return; - } for (Validator validator : validators) { if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) { throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget()); diff --git a/spring-core/src/main/java/org/springframework/util/CustomizableThreadCreator.java b/spring-core/src/main/java/org/springframework/util/CustomizableThreadCreator.java index 379e8330068..38c9efbb58c 100644 --- a/spring-core/src/main/java/org/springframework/util/CustomizableThreadCreator.java +++ b/spring-core/src/main/java/org/springframework/util/CustomizableThreadCreator.java @@ -41,6 +41,7 @@ public class CustomizableThreadCreator implements Serializable { private boolean daemon = false; + @Nullable private ThreadGroup threadGroup; private final AtomicInteger threadCount = new AtomicInteger(0); diff --git a/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java b/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java index b9a9d470a9c..6f7aba47727 100644 --- a/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java +++ b/spring-core/src/main/java/org/springframework/util/concurrent/ListenableFutureCallbackRegistry.java @@ -132,7 +132,7 @@ public class ListenableFutureCallbackRegistry { * added callbacks with the given result. * @param result the result to trigger the callbacks with */ - public void success(T result) { + public void success(@Nullable T result) { synchronized (this.mutex) { this.state = State.SUCCESS; this.result = result; diff --git a/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLReader.java b/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLReader.java index 379035c4ace..44fdd953d8a 100644 --- a/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLReader.java +++ b/spring-core/src/main/java/org/springframework/util/xml/AbstractXMLReader.java @@ -144,6 +144,7 @@ abstract class AbstractXMLReader implements XMLReader { * handler. The property name for a lexical handler is {@code http://xml.org/sax/properties/lexical-handler}. */ @Override + @Nullable public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { return this.lexicalHandler; diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java index 42160c5960f..630a83384cf 100755 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java @@ -244,6 +244,19 @@ public class CallMetaDataContext { } + /** + * Initialize this class with metadata from the database. + * @param dataSource the DataSource used to retrieve metadata + */ + public void initializeMetaData(DataSource dataSource) { + this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this); + } + + private CallMetaDataProvider obtainMetaDataProvider() { + Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider - call initializeMetaData first"); + return this.metaDataProvider; + } + /** * Create a ReturnResultSetParameter/SqlOutParameter depending on the support provided * by the JDBC driver used for the database in use. @@ -252,13 +265,13 @@ public class CallMetaDataContext { * @return the appropriate SqlParameter */ public SqlParameter createReturnResultSetParameter(String parameterName, RowMapper rowMapper) { - Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); - if (this.metaDataProvider.isReturnResultSetSupported()) { + CallMetaDataProvider provider = obtainMetaDataProvider(); + if (provider.isReturnResultSetSupported()) { return new SqlReturnResultSet(parameterName, rowMapper); } else { - if (this.metaDataProvider.isRefCursorSupported()) { - return new SqlOutParameter(parameterName, this.metaDataProvider.getRefCursorSqlType(), rowMapper); + if (provider.isRefCursorSupported()) { + return new SqlOutParameter(parameterName, provider.getRefCursorSqlType(), rowMapper); } else { throw new InvalidDataAccessApiUsageException("Return of a ResultSet from a stored procedure is not supported."); @@ -290,14 +303,6 @@ public class CallMetaDataContext { return this.callParameters; } - /** - * Initialize this class with metadata from the database. - * @param dataSource the DataSource used to retrieve metadata - */ - public void initializeMetaData(DataSource dataSource) { - this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this); - } - /** * Process the list of parameters provided, and if procedure column metadata is used, * the parameters will be matched against the metadata information and any missing @@ -312,7 +317,7 @@ public class CallMetaDataContext { * Reconcile the provided parameters with available metadata and add new ones where appropriate. */ protected List reconcileParameters(List parameters) { - Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); + CallMetaDataProvider provider = obtainMetaDataProvider(); final List declaredReturnParams = new ArrayList<>(); final Map declaredParams = new LinkedHashMap<>(); @@ -321,7 +326,7 @@ public class CallMetaDataContext { List metaDataParamNames = new ArrayList<>(); // Get the names of the meta data parameters - for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { + for (CallParameterMetaData meta : provider.getCallParameterMetaData()) { if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { metaDataParamNames.add(lowerCase(meta.getParameterName())); } @@ -338,7 +343,7 @@ public class CallMetaDataContext { throw new IllegalArgumentException("Anonymous parameters not supported for calls - " + "please specify a name for the parameter of SQL type " + param.getSqlType()); } - String paramNameToMatch = lowerCase(this.metaDataProvider.parameterNameToUse(paramName)); + String paramNameToMatch = lowerCase(provider.parameterNameToUse(paramName)); declaredParams.put(paramNameToMatch, param); if (param instanceof SqlOutParameter) { outParamNames.add(paramName); @@ -360,24 +365,23 @@ public class CallMetaDataContext { List workParams = new ArrayList<>(); workParams.addAll(declaredReturnParams); - if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { + if (!provider.isProcedureColumnMetaDataUsed()) { workParams.addAll(declaredParams.values()); return workParams; } Map limitedInParamNamesMap = new HashMap<>(this.limitedInParameterNames.size()); for (String limitedParamName : this.limitedInParameterNames) { - limitedInParamNamesMap.put( - lowerCase(this.metaDataProvider.parameterNameToUse(limitedParamName)), limitedParamName); + limitedInParamNamesMap.put(lowerCase(provider.parameterNameToUse(limitedParamName)), limitedParamName); } - for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { + for (CallParameterMetaData meta : provider.getCallParameterMetaData()) { String paramName = meta.getParameterName(); String paramNameToCheck = null; if (paramName != null) { - paramNameToCheck = lowerCase(this.metaDataProvider.parameterNameToUse(paramName)); + paramNameToCheck = lowerCase(provider.parameterNameToUse(paramName)); } - String paramNameToUse = this.metaDataProvider.parameterNameToUse(paramName); + String paramNameToUse = provider.parameterNameToUse(paramName); if (declaredParams.containsKey(paramNameToCheck) || (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) { SqlParameter param; @@ -409,7 +413,7 @@ public class CallMetaDataContext { else { if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { if (!isFunction() && !isReturnValueRequired() && paramName != null && - this.metaDataProvider.byPassReturnParameter(paramName)) { + provider.byPassReturnParameter(paramName)) { if (logger.isDebugEnabled()) { logger.debug("Bypassing metadata return parameter for '" + paramName + "'"); } @@ -417,7 +421,7 @@ public class CallMetaDataContext { else { String returnNameToUse = (StringUtils.hasLength(paramNameToUse) ? paramNameToUse : getFunctionReturnName()); - workParams.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta)); + workParams.add(provider.createDefaultOutParameter(returnNameToUse, meta)); if (isFunction()) { setFunctionReturnName(returnNameToUse); outParamNames.add(returnNameToUse); @@ -432,14 +436,14 @@ public class CallMetaDataContext { paramNameToUse = ""; } if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) { - workParams.add(this.metaDataProvider.createDefaultOutParameter(paramNameToUse, meta)); + workParams.add(provider.createDefaultOutParameter(paramNameToUse, meta)); outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { logger.debug("Added metadata out parameter for '" + paramNameToUse + "'"); } } else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) { - workParams.add(this.metaDataProvider.createDefaultInOutParameter(paramNameToUse, meta)); + workParams.add(provider.createDefaultInOutParameter(paramNameToUse, meta)); outParamNames.add(paramNameToUse); if (logger.isDebugEnabled()) { logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'"); @@ -448,7 +452,7 @@ public class CallMetaDataContext { else { if (this.limitedInParameterNames.isEmpty() || limitedInParamNamesMap.containsKey(lowerCase(paramNameToUse))) { - workParams.add(this.metaDataProvider.createDefaultInParameter(paramNameToUse, meta)); + workParams.add(provider.createDefaultInParameter(paramNameToUse, meta)); if (logger.isDebugEnabled()) { logger.debug("Added metadata in parameter for '" + paramNameToUse + "'"); } @@ -473,8 +477,6 @@ public class CallMetaDataContext { * @return a Map containing the matched parameter names with the value taken from the input */ public Map matchInParameterValuesWithCallParameters(SqlParameterSource parameterSource) { - Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); - // For parameter source lookups we need to provide case-insensitive lookup support // since the database metadata is not necessarily providing case sensitive parameter names. Map caseInsensitiveParameterNames = @@ -485,7 +487,7 @@ public class CallMetaDataContext { for (SqlParameter parameter : this.callParameters) { if (parameter.isInputValueProvided()) { String parameterName = parameter.getName(); - String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); + String parameterNameToMatch = obtainMetaDataProvider().parameterNameToUse(parameterName); if (parameterNameToMatch != null) { callParameterNames.put(parameterNameToMatch.toLowerCase(), parameterName); } @@ -538,8 +540,8 @@ public class CallMetaDataContext { * @return a Map containing the matched parameter names with the value taken from the input */ public Map matchInParameterValuesWithCallParameters(Map inParameters) { - Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); - if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { + CallMetaDataProvider provider = obtainMetaDataProvider(); + if (!provider.isProcedureColumnMetaDataUsed()) { return inParameters; } @@ -547,7 +549,7 @@ public class CallMetaDataContext { for (SqlParameter parameter : this.callParameters) { if (parameter.isInputValueProvided()) { String parameterName = parameter.getName(); - String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); + String parameterNameToMatch = provider.parameterNameToUse(parameterName); if (parameterNameToMatch != null) { callParameterNames.put(parameterNameToMatch.toLowerCase(), parameterName); } @@ -556,7 +558,7 @@ public class CallMetaDataContext { Map matchedParameters = new HashMap<>(inParameters.size()); for (String parameterName : inParameters.keySet()) { - String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); + String parameterNameToMatch = provider.parameterNameToUse(parameterName); String callParameterName = callParameterNames.get(lowerCase(parameterNameToMatch)); if (callParameterName == null) { if (logger.isDebugEnabled()) { @@ -577,7 +579,7 @@ public class CallMetaDataContext { if (matchedParameters.size() < callParameterNames.size()) { for (String parameterName : callParameterNames.keySet()) { - String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); + String parameterNameToMatch = provider.parameterNameToUse(parameterName); String callParameterName = callParameterNames.get(lowerCase(parameterNameToMatch)); if (!matchedParameters.containsKey(callParameterName)) { logger.warn("Unable to locate the corresponding parameter value for '" + parameterName + diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java index 610362e442c..2962b791c74 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/TableMetaDataContext.java @@ -33,6 +33,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils; import org.springframework.jdbc.support.JdbcUtils; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; /** * Class to manage context metadata used for the configuration @@ -47,13 +48,16 @@ public class TableMetaDataContext { /** Logger available to subclasses */ protected final Log logger = LogFactory.getLog(getClass()); - /** name of table for this context **/ + /** Name of table for this context */ + @Nullable private String tableName; - /** name of catalog for this context **/ + /** Name of catalog for this context */ + @Nullable private String catalogName; - /** name of schema for this context **/ + /** Name of schema for this context */ + @Nullable private String schemaName; /** List of columns objects to be used in this context */ @@ -66,6 +70,7 @@ public class TableMetaDataContext { private boolean overrideIncludeSynonymsDefault = false; /** the provider of table meta data */ + @Nullable private TableMetaDataProvider metaDataProvider; /** are we using generated key columns */ @@ -153,41 +158,6 @@ public class TableMetaDataContext { return this.tableColumns; } - /** - * Does this database support the JDBC 3.0 feature of retrieving generated keys - * {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}? - */ - public boolean isGetGeneratedKeysSupported() { - return this.metaDataProvider.isGetGeneratedKeysSupported(); - } - - /** - * Does this database support simple query to retrieve generated keys - * when the JDBC 3.0 feature is not supported. - * {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}? - */ - public boolean isGetGeneratedKeysSimulated() { - return this.metaDataProvider.isGetGeneratedKeysSimulated(); - } - - /** - * Does this database support simple query to retrieve generated keys - * when the JDBC 3.0 feature is not supported. - * {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}? - */ - @Nullable - public String getSimulationQueryForGetGeneratedKey(String tableName, String keyColumnName) { - return this.metaDataProvider.getSimpleQueryForGetGeneratedKey(tableName, keyColumnName); - } - - /** - * Is a column name String array for retrieving generated keys supported? - * {@link java.sql.Connection#createStruct(String, Object[])}? - */ - public boolean isGeneratedKeysColumnNameArraySupported() { - return this.metaDataProvider.isGeneratedKeysColumnNameArraySupported(); - } - /** * Process the current meta data with the provided configuration options. @@ -200,6 +170,11 @@ public class TableMetaDataContext { this.tableColumns = reconcileColumnsToUse(declaredColumns, generatedKeyNames); } + private TableMetaDataProvider obtainMetaDataProvider() { + Assert.state(this.metaDataProvider != null, "No TableMetaDataProvider - call processMetaData first"); + return this.metaDataProvider; + } + /** * Compare columns created from metadata with declared columns and return a reconciled list. * @param declaredColumns declared column names @@ -217,7 +192,7 @@ public class TableMetaDataContext { keys.add(key.toUpperCase()); } List columns = new ArrayList<>(); - for (TableParameterMetaData meta : metaDataProvider.getTableParameterMetaData()) { + for (TableParameterMetaData meta : obtainMetaDataProvider().getTableParameterMetaData()) { if (!keys.contains(meta.getParameterName().toUpperCase())) { columns.add(meta.getParameterName()); } @@ -336,7 +311,7 @@ public class TableMetaDataContext { */ public int[] createInsertTypes() { int[] types = new int[getTableColumns().size()]; - List parameters = this.metaDataProvider.getTableParameterMetaData(); + List parameters = obtainMetaDataProvider().getTableParameterMetaData(); Map parameterMap = new LinkedHashMap<>(parameters.size()); for (TableParameterMetaData tpmd : parameters) { @@ -361,4 +336,40 @@ public class TableMetaDataContext { return types; } + + /** + * Does this database support the JDBC 3.0 feature of retrieving generated keys + * {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}? + */ + public boolean isGetGeneratedKeysSupported() { + return obtainMetaDataProvider().isGetGeneratedKeysSupported(); + } + + /** + * Does this database support simple query to retrieve generated keys + * when the JDBC 3.0 feature is not supported. + * {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}? + */ + public boolean isGetGeneratedKeysSimulated() { + return obtainMetaDataProvider().isGetGeneratedKeysSimulated(); + } + + /** + * Does this database support simple query to retrieve generated keys + * when the JDBC 3.0 feature is not supported. + * {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}? + */ + @Nullable + public String getSimulationQueryForGetGeneratedKey(String tableName, String keyColumnName) { + return obtainMetaDataProvider().getSimpleQueryForGetGeneratedKey(tableName, keyColumnName); + } + + /** + * Is a column name String array for retrieving generated keys supported? + * {@link java.sql.Connection#createStruct(String, Object[])}? + */ + public boolean isGeneratedKeysColumnNameArraySupported() { + return obtainMetaDataProvider().isGeneratedKeysColumnNameArraySupported(); + } + } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java index f3209e01e02..a2bcb4c5e4a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/AbstractDriverBasedDataSource.java @@ -21,7 +21,6 @@ import java.sql.SQLException; import java.util.Properties; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; /** * Abstract base class for JDBC {@link javax.sql.DataSource} implementations @@ -58,8 +57,7 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { * @see java.sql.Driver#connect(String, java.util.Properties) */ public void setUrl(@Nullable String url) { - Assert.hasText(url, "Property 'url' must not be empty"); - this.url = url.trim(); + this.url = (url != null ? url.trim() : null); } /** diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java index 9790e4ebfdb..e0559e4fbed 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/CustomSQLErrorCodesTranslation.java @@ -33,6 +33,7 @@ public class CustomSQLErrorCodesTranslation { private String[] errorCodes = new String[0]; + @Nullable private Class exceptionClass; diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java b/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java index cb2c925b4bb..dd55e88daa9 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/TransactionAwareConnectionFactoryProxy.java @@ -79,11 +79,11 @@ import org.springframework.util.Assert; public class TransactionAwareConnectionFactoryProxy implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory { - private boolean synchedLocalTransactionAllowed = false; - @Nullable private ConnectionFactory targetConnectionFactory; + private boolean synchedLocalTransactionAllowed = false; + /** * Create a new TransactionAwareConnectionFactoryProxy. @@ -103,16 +103,18 @@ public class TransactionAwareConnectionFactoryProxy /** * Set the target ConnectionFactory that this ConnectionFactory should delegate to. */ - public final void setTargetConnectionFactory(@Nullable ConnectionFactory targetConnectionFactory) { + public final void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) { + Assert.notNull(targetConnectionFactory, "'targetConnectionFactory' must not be null"); this.targetConnectionFactory = targetConnectionFactory; } /** * Return the target ConnectionFactory that this ConnectionFactory should delegate to. */ - @Nullable protected ConnectionFactory getTargetConnectionFactory() { - return this.targetConnectionFactory; + ConnectionFactory target = this.targetConnectionFactory; + Assert.state(target != null, "'targetConnectionFactory' is required"); + return target; } /** @@ -141,19 +143,19 @@ public class TransactionAwareConnectionFactoryProxy @Override public Connection createConnection() throws JMSException { - Connection targetConnection = this.targetConnectionFactory.createConnection(); + Connection targetConnection = getTargetConnectionFactory().createConnection(); return getTransactionAwareConnectionProxy(targetConnection); } @Override public Connection createConnection(String username, String password) throws JMSException { - Connection targetConnection = obtainTargetConnectionFactory().createConnection(username, password); + Connection targetConnection = getTargetConnectionFactory().createConnection(username, password); return getTransactionAwareConnectionProxy(targetConnection); } @Override public QueueConnection createQueueConnection() throws JMSException { - ConnectionFactory target = obtainTargetConnectionFactory(); + ConnectionFactory target = getTargetConnectionFactory(); if (!(target instanceof QueueConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory"); } @@ -163,7 +165,7 @@ public class TransactionAwareConnectionFactoryProxy @Override public QueueConnection createQueueConnection(String username, String password) throws JMSException { - ConnectionFactory target = obtainTargetConnectionFactory(); + ConnectionFactory target = getTargetConnectionFactory(); if (!(target instanceof QueueConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory"); } @@ -173,7 +175,7 @@ public class TransactionAwareConnectionFactoryProxy @Override public TopicConnection createTopicConnection() throws JMSException { - ConnectionFactory target = obtainTargetConnectionFactory(); + ConnectionFactory target = getTargetConnectionFactory(); if (!(target instanceof TopicConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory"); } @@ -183,7 +185,7 @@ public class TransactionAwareConnectionFactoryProxy @Override public TopicConnection createTopicConnection(String username, String password) throws JMSException { - ConnectionFactory target = obtainTargetConnectionFactory(); + ConnectionFactory target = getTargetConnectionFactory(); if (!(target instanceof TopicConnectionFactory)) { throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory"); } @@ -193,28 +195,22 @@ public class TransactionAwareConnectionFactoryProxy @Override public JMSContext createContext() { - return obtainTargetConnectionFactory().createContext(); + return getTargetConnectionFactory().createContext(); } @Override public JMSContext createContext(String userName, String password) { - return obtainTargetConnectionFactory().createContext(userName, password); + return getTargetConnectionFactory().createContext(userName, password); } @Override public JMSContext createContext(String userName, String password, int sessionMode) { - return obtainTargetConnectionFactory().createContext(userName, password, sessionMode); + return getTargetConnectionFactory().createContext(userName, password, sessionMode); } @Override public JMSContext createContext(int sessionMode) { - return obtainTargetConnectionFactory().createContext(sessionMode); - } - - private ConnectionFactory obtainTargetConnectionFactory() { - ConnectionFactory target = getTargetConnectionFactory(); - Assert.state(target != null, "'targetConnectionFactory' is required"); - return target; + return getTargetConnectionFactory().createContext(sessionMode); } @@ -265,14 +261,14 @@ public class TransactionAwareConnectionFactoryProxy } else if (Session.class == method.getReturnType()) { Session session = ConnectionFactoryUtils.getTransactionalSession( - obtainTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed()); + getTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed()); if (session != null) { return getCloseSuppressingSessionProxy(session); } } else if (QueueSession.class == method.getReturnType()) { QueueSession session = ConnectionFactoryUtils.getTransactionalQueueSession( - (QueueConnectionFactory) obtainTargetConnectionFactory(), (QueueConnection) this.target, + (QueueConnectionFactory) getTargetConnectionFactory(), (QueueConnection) this.target, isSynchedLocalTransactionAllowed()); if (session != null) { return getCloseSuppressingSessionProxy(session); @@ -280,7 +276,7 @@ public class TransactionAwareConnectionFactoryProxy } else if (TopicSession.class == method.getReturnType()) { TopicSession session = ConnectionFactoryUtils.getTransactionalTopicSession( - (TopicConnectionFactory) obtainTargetConnectionFactory(), (TopicConnection) this.target, + (TopicConnectionFactory) getTargetConnectionFactory(), (TopicConnection) this.target, isSynchedLocalTransactionAllowed()); if (session != null) { return getCloseSuppressingSessionProxy(session); diff --git a/spring-jms/src/main/java/org/springframework/jms/core/JmsTemplate.java b/spring-jms/src/main/java/org/springframework/jms/core/JmsTemplate.java index 1477d122da5..794c5bc99a7 100644 --- a/spring-jms/src/main/java/org/springframework/jms/core/JmsTemplate.java +++ b/spring-jms/src/main/java/org/springframework/jms/core/JmsTemplate.java @@ -95,6 +95,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations @Nullable private Object defaultDestination; + @Nullable private MessageConverter messageConverter; @@ -228,13 +229,14 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations * @see #receiveAndConvert * @see org.springframework.jms.support.converter.SimpleMessageConverter */ - public void setMessageConverter(MessageConverter messageConverter) { + public void setMessageConverter(@Nullable MessageConverter messageConverter) { this.messageConverter = messageConverter; } /** * Return the message converter for this template. */ + @Nullable public MessageConverter getMessageConverter() { return this.messageConverter; } diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java index e4f79f4110d..9ae3d41e5f7 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java @@ -65,6 +65,7 @@ public abstract class AbstractAdaptableMessageListener private DestinationResolver destinationResolver = new DynamicDestinationResolver(); + @Nullable private MessageConverter messageConverter = new SimpleMessageConverter(); private final MessagingMessageConverterAdapter messagingMessageConverter = new MessagingMessageConverterAdapter(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java index 066643bff50..0bbfc3ca2bc 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java @@ -232,11 +232,15 @@ public abstract class AbstractMethodMessageHandler this.returnValueHandlers.addHandlers(initReturnValueHandlers()); } - for (String beanName : this.applicationContext.getBeanNamesForType(Object.class)) { + ApplicationContext context = getApplicationContext(); + if (context == null) { + return; + } + for (String beanName : context.getBeanNamesForType(Object.class)) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class beanType = null; try { - beanType = this.applicationContext.getType(beanName); + beanType = context.getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. @@ -279,8 +283,15 @@ public abstract class AbstractMethodMessageHandler * @param handler the handler to check, either an instance of a Spring bean name */ protected final void detectHandlerMethods(final Object handler) { - Class handlerType = (handler instanceof String ? - this.applicationContext.getType((String) handler) : handler.getClass()); + Class handlerType; + if (handler instanceof String) { + ApplicationContext context = getApplicationContext(); + Assert.state(context != null, "ApplicationContext is required for resolving handler bean names"); + handlerType = context.getType((String) handler); + } + else { + handlerType = handler.getClass(); + } if (handlerType != null) { final Class userType = ClassUtils.getUserClass(handlerType); @@ -338,9 +349,10 @@ public abstract class AbstractMethodMessageHandler protected HandlerMethod createHandlerMethod(Object handler, Method method) { HandlerMethod handlerMethod; if (handler instanceof String) { + ApplicationContext context = getApplicationContext(); + Assert.state(context != null, "ApplicationContext is required for resolving handler bean names"); String beanName = (String) handler; - handlerMethod = new HandlerMethod(beanName, - this.applicationContext.getAutowireCapableBeanFactory(), method); + handlerMethod = new HandlerMethod(beanName, context.getAutowireCapableBeanFactory(), method); } else { handlerMethod = new HandlerMethod(handler, method); @@ -645,7 +657,7 @@ public abstract class AbstractMethodMessageHandler } @Override - public void onSuccess(Object result) { + public void onSuccess(@Nullable Object result) { try { MethodParameter returnType = this.handlerMethod.getAsyncReturnValueType(result); returnValueHandlers.handleReturnValue(result, returnType, this.message); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java index 23910f3e2ff..be8adc8b56a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java @@ -252,7 +252,7 @@ public class InvocableHandlerMethod extends HandlerMethod { } - MethodParameter getAsyncReturnValueType(Object returnValue) { + MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) { return new AsyncResultMethodParameter(returnValue); } @@ -264,7 +264,7 @@ public class InvocableHandlerMethod extends HandlerMethod { private final ResolvableType returnType; - public AsyncResultMethodParameter(Object returnValue) { + public AsyncResultMethodParameter(@Nullable Object returnValue) { super(-1); this.returnValue = returnValue; this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java index cee9dfb8341..9b2b8567866 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java @@ -54,6 +54,7 @@ public class SimpMessagingTemplate extends AbstractMessageSendingTemplate initArgumentResolvers() { - ConfigurableBeanFactory beanFactory = (getApplicationContext() instanceof ConfigurableApplicationContext ? - ((ConfigurableApplicationContext) getApplicationContext()).getBeanFactory() : null); + ApplicationContext context = getApplicationContext(); + ConfigurableBeanFactory beanFactory = (context instanceof ConfigurableApplicationContext ? + ((ConfigurableApplicationContext) context).getBeanFactory() : null); List resolvers = new ArrayList<>(); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java b/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java index f133dfd7029..c115556b516 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/IdTimestampMessageHeaderInitializer.java @@ -16,8 +16,6 @@ package org.springframework.messaging.support; -import java.util.UUID; - import org.springframework.lang.Nullable; import org.springframework.messaging.MessageHeaders; import org.springframework.util.IdGenerator; @@ -31,6 +29,10 @@ import org.springframework.util.IdGenerator; */ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitializer { + private static final IdGenerator ID_VALUE_NONE_GENERATOR = () -> MessageHeaders.ID_VALUE_NONE; + + + @Nullable private IdGenerator idGenerator; private boolean enableTimestamp; @@ -41,20 +43,12 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial * instances with. *

By default this property is set to {@code null} in which case the default * IdGenerator of {@link org.springframework.messaging.MessageHeaders} is used. - *

To have no id's generated at all, see {@link #setDisableIdGeneration()}. + *

To have no ids generated at all, see {@link #setDisableIdGeneration()}. */ public void setIdGenerator(@Nullable IdGenerator idGenerator) { this.idGenerator = idGenerator; } - /** - * A shortcut for calling {@link #setIdGenerator(org.springframework.util.IdGenerator)} - * with an id generation strategy to disable id generation completely. - */ - public void setDisableIdGeneration() { - this.idGenerator = ID_VALUE_NONE_GENERATOR; - } - /** * Return the configured {@code IdGenerator}, if any. */ @@ -63,6 +57,14 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial return this.idGenerator; } + /** + * A shortcut for calling {@link #setIdGenerator} with an id generation strategy + * to disable id generation completely. + */ + public void setDisableIdGeneration() { + this.idGenerator = ID_VALUE_NONE_GENERATOR; + } + /** * Whether to enable the automatic addition of the * {@link org.springframework.messaging.MessageHeaders#TIMESTAMP} header on @@ -90,12 +92,4 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial headerAccessor.setEnableTimestamp(isEnableTimestamp()); } - - private static final IdGenerator ID_VALUE_NONE_GENERATOR = new IdGenerator() { - @Override - public UUID generateId() { - return MessageHeaders.ID_VALUE_NONE; - } - }; - } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/AbstractMonoToListenableFutureAdapter.java b/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/AbstractMonoToListenableFutureAdapter.java index 2a09105f16f..22b68f5b05b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/AbstractMonoToListenableFutureAdapter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/AbstractMonoToListenableFutureAdapter.java @@ -24,6 +24,7 @@ import java.util.concurrent.TimeoutException; import reactor.core.publisher.Mono; import reactor.core.publisher.MonoProcessor; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.concurrent.FailureCallback; import org.springframework.util.concurrent.ListenableFuture; @@ -67,12 +68,14 @@ abstract class AbstractMonoToListenableFutureAdapter implements Listenable @Override + @Nullable public T get() throws InterruptedException { S result = this.monoProcessor.block(); return adapt(result); } @Override + @Nullable public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { Assert.notNull(unit, "TimeUnit must not be null"); Duration duration = Duration.ofMillis(TimeUnit.MILLISECONDS.convert(timeout, unit)); @@ -111,6 +114,7 @@ abstract class AbstractMonoToListenableFutureAdapter implements Listenable } - protected abstract T adapt(S result); + @Nullable + protected abstract T adapt(@Nullable S result); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/MonoToListenableFutureAdapter.java b/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/MonoToListenableFutureAdapter.java index 2f83d78932b..0eb76b88654 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/MonoToListenableFutureAdapter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/tcp/reactor/MonoToListenableFutureAdapter.java @@ -18,6 +18,8 @@ package org.springframework.messaging.tcp.reactor; import reactor.core.publisher.Mono; +import org.springframework.lang.Nullable; + /** * A Mono-to-ListenableFuture adapter where the source and the target from * the Promise and the ListenableFuture respectively are of the same type. @@ -33,7 +35,7 @@ class MonoToListenableFutureAdapter extends AbstractMonoToListenableFutureAda } @Override - protected T adapt(T result) { + protected T adapt(@Nullable T result) { return result; } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/AbstractJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/AbstractJpaVendorAdapter.java index a756c780fd7..20bb9a5f1cd 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/AbstractJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/AbstractJpaVendorAdapter.java @@ -36,6 +36,7 @@ public abstract class AbstractJpaVendorAdapter implements JpaVendorAdapter { private Database database = Database.DEFAULT; + @Nullable private String databasePlatform; private boolean generateDdl = false; @@ -47,14 +48,13 @@ public abstract class AbstractJpaVendorAdapter implements JpaVendorAdapter { * Specify the target database to operate on, as a value of the {@code Database} enum: * DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER, SYBASE */ - public void setDatabase(@Nullable Database database) { + public void setDatabase(Database database) { this.database = database; } /** * Return the target database to operate on. */ - @Nullable protected Database getDatabase() { return this.database; } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java index f8d437740e1..244a1e290aa 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/EclipseLinkJpaVendorAdapter.java @@ -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. @@ -65,7 +65,7 @@ public class EclipseLinkJpaVendorAdapter extends AbstractJpaVendorAdapter { if (getDatabasePlatform() != null) { jpaProperties.put(PersistenceUnitProperties.TARGET_DATABASE, getDatabasePlatform()); } - else if (getDatabase() != null) { + else { String targetDatabase = determineTargetDatabaseName(getDatabase()); if (targetDatabase != null) { jpaProperties.put(PersistenceUnitProperties.TARGET_DATABASE, targetDatabase); diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java index 5a919c70fb9..cd2e5f750e8 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java @@ -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. @@ -18,7 +18,6 @@ package org.springframework.orm.jpa.vendor; import java.util.HashMap; import java.util.Map; - import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.spi.PersistenceProvider; @@ -117,7 +116,7 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { if (getDatabasePlatform() != null) { jpaProperties.put(AvailableSettings.DIALECT, getDatabasePlatform()); } - else if (getDatabase() != null) { + else { Class databaseDialectClass = determineDatabaseDialectClass(getDatabase()); if (databaseDialectClass != null) { jpaProperties.put(AvailableSettings.DIALECT, databaseDialectClass.getName()); diff --git a/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java index ba6314a66d0..3761dc17dce 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java @@ -54,6 +54,7 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv private List supportedMediaTypes = Collections.emptyList(); + @Nullable private Charset defaultCharset; diff --git a/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java b/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java index 1ad598224f3..0a928c4f165 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java +++ b/spring-web/src/main/java/org/springframework/web/bind/WebDataBinder.java @@ -75,8 +75,10 @@ public class WebDataBinder extends DataBinder { */ public static final String DEFAULT_FIELD_DEFAULT_PREFIX = "!"; + @Nullable private String fieldMarkerPrefix = DEFAULT_FIELD_MARKER_PREFIX; + @Nullable private String fieldDefaultPrefix = DEFAULT_FIELD_DEFAULT_PREFIX; private boolean bindEmptyMultipartFiles = true; @@ -124,13 +126,14 @@ public class WebDataBinder extends DataBinder { * detect an empty field and automatically reset its value. * @see #DEFAULT_FIELD_MARKER_PREFIX */ - public void setFieldMarkerPrefix(String fieldMarkerPrefix) { + public void setFieldMarkerPrefix(@Nullable String fieldMarkerPrefix) { this.fieldMarkerPrefix = fieldMarkerPrefix; } /** * Return the prefix for parameters that mark potentially empty fields. */ + @Nullable public String getFieldMarkerPrefix() { return this.fieldMarkerPrefix; } @@ -149,13 +152,14 @@ public class WebDataBinder extends DataBinder { * marker for the given field. * @see #DEFAULT_FIELD_DEFAULT_PREFIX */ - public void setFieldDefaultPrefix(String fieldDefaultPrefix) { + public void setFieldDefaultPrefix(@Nullable String fieldDefaultPrefix) { this.fieldDefaultPrefix = fieldDefaultPrefix; } /** * Return the prefix for parameters that mark default fields. */ + @Nullable public String getFieldDefaultPrefix() { return this.fieldDefaultPrefix; } diff --git a/spring-web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java b/spring-web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java index 9fea43b57ae..e6f4266cab7 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/AbstractRefreshableWebApplicationContext.java @@ -117,7 +117,7 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR @Override public void setServletConfig(@Nullable ServletConfig servletConfig) { this.servletConfig = servletConfig; - if (this.servletContext == null) { + if (servletConfig != null && this.servletContext == null) { setServletContext(servletConfig.getServletContext()); } } @@ -131,7 +131,9 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR @Override public void setNamespace(@Nullable String namespace) { this.namespace = namespace; - setDisplayName(namespace != null ? "WebApplicationContext for namespace '" + namespace + "'" : null); + if (namespace != null) { + setDisplayName("WebApplicationContext for namespace '" + namespace + "'"); + } } @Override diff --git a/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java b/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java index 786ab602aca..0d133f164af 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/StaticWebApplicationContext.java @@ -93,7 +93,7 @@ public class StaticWebApplicationContext extends StaticApplicationContext @Override public void setServletConfig(@Nullable ServletConfig servletConfig) { this.servletConfig = servletConfig; - if (this.servletContext == null) { + if (servletConfig != null && this.servletContext == null) { this.servletContext = servletConfig.getServletContext(); } } @@ -107,7 +107,9 @@ public class StaticWebApplicationContext extends StaticApplicationContext @Override public void setNamespace(@Nullable String namespace) { this.namespace = namespace; - setDisplayName(namespace != null ? "WebApplicationContext for namespace '" + namespace + "'" : null); + if (namespace != null) { + setDisplayName("WebApplicationContext for namespace '" + namespace + "'"); + } } @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java index 66bcc086da9..a65908371be 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/RedirectView.java @@ -62,6 +62,7 @@ public class RedirectView extends AbstractUrlBasedView { private boolean propagateQuery = false; + @Nullable private String[] hosts; @@ -111,17 +112,14 @@ public class RedirectView extends AbstractUrlBasedView { * {@link HttpStatus#TEMPORARY_REDIRECT} or * {@link HttpStatus#PERMANENT_REDIRECT}. */ - public void setStatusCode(@Nullable HttpStatus statusCode) { - if (statusCode != null) { - Assert.isTrue(statusCode.is3xxRedirection(), "Must be a redirection (3xx status code)"); - } + public void setStatusCode(HttpStatus statusCode) { + Assert.isTrue(statusCode.is3xxRedirection(), "Must be a redirection (3xx status code)"); this.statusCode = statusCode; } /** * Get the redirect status code to use. */ - @Nullable public HttpStatus getStatusCode() { return this.statusCode; } @@ -150,13 +148,14 @@ public class RedirectView extends AbstractUrlBasedView { *

If not set (the default) all redirect URLs are encoded. * @param hosts one or more application hosts */ - public void setHosts(String... hosts) { + public void setHosts(@Nullable String... hosts) { this.hosts = hosts; } /** * Return the configured application hosts. */ + @Nullable public String[] getHosts() { return this.hosts; } @@ -165,9 +164,6 @@ public class RedirectView extends AbstractUrlBasedView { @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); - if (getStatusCode() == null) { - throw new IllegalArgumentException("Property 'statusCode' is required"); - } } @@ -185,8 +181,8 @@ public class RedirectView extends AbstractUrlBasedView { * Convert model to request parameters and redirect to the given URL. */ @Override - protected Mono renderInternal(Map model, MediaType contentType, - ServerWebExchange exchange) { + protected Mono renderInternal( + Map model, @Nullable MediaType contentType, ServerWebExchange exchange) { String targetUrl = createTargetUrl(model, exchange); return sendRedirect(targetUrl, exchange); @@ -296,10 +292,7 @@ public class RedirectView extends AbstractUrlBasedView { ServerHttpResponse response = exchange.getResponse(); String encodedURL = (isRemoteHost(targetUrl) ? targetUrl : response.encodeUrl(targetUrl)); response.getHeaders().setLocation(URI.create(encodedURL)); - HttpStatus status = getStatusCode(); - if (status != null) { - response.setStatusCode(status); - } + response.setStatusCode(getStatusCode()); return Mono.empty(); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java index 710cdac797b..5f398af2567 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/CookieLocaleResolver.java @@ -105,8 +105,6 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte * Specify whether this resolver's cookies should be compliant with BCP 47 * language tags instead of Java's legacy locale specification format. * The default is {@code false}. - *

Note: This mode requires JDK 7 or higher. Set this flag to {@code true} - * for BCP 47 compliance on JDK 7+ only. * @since 4.3 * @see Locale#forLanguageTag(String) * @see Locale#toLanguageTag() @@ -182,43 +180,48 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte private void parseLocaleCookieIfNecessary(HttpServletRequest request) { if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) { - // Retrieve and parse cookie value. - Cookie cookie = WebUtils.getCookie(request, getCookieName()); Locale locale = null; TimeZone timeZone = null; - if (cookie != null) { - String value = cookie.getValue(); - String localePart = value; - String timeZonePart = null; - int spaceIndex = localePart.indexOf(' '); - if (spaceIndex != -1) { - localePart = value.substring(0, spaceIndex); - timeZonePart = value.substring(spaceIndex + 1); - } - try { - locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null); - if (timeZonePart != null) { - timeZone = StringUtils.parseTimeZoneString(timeZonePart); + + // Retrieve and parse cookie value. + String cookieName = getCookieName(); + if (cookieName != null) { + Cookie cookie = WebUtils.getCookie(request, cookieName); + if (cookie != null) { + String value = cookie.getValue(); + String localePart = value; + String timeZonePart = null; + int spaceIndex = localePart.indexOf(' '); + if (spaceIndex != -1) { + localePart = value.substring(0, spaceIndex); + timeZonePart = value.substring(spaceIndex + 1); } - } - catch (IllegalArgumentException ex) { - if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) { - // Error dispatch: ignore locale/timezone parse exceptions - if (logger.isDebugEnabled()) { - logger.debug("Ignoring invalid locale cookie '" + getCookieName() + - "' with value [" + value + "] due to error dispatch: " + ex.getMessage()); + try { + locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null); + if (timeZonePart != null) { + timeZone = StringUtils.parseTimeZoneString(timeZonePart); } } - else { - throw new IllegalStateException("Invalid locale cookie '" + getCookieName() + - "' with value [" + value + "]: " + ex.getMessage()); + catch (IllegalArgumentException ex) { + if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) { + // Error dispatch: ignore locale/timezone parse exceptions + if (logger.isDebugEnabled()) { + logger.debug("Ignoring invalid locale cookie '" + cookieName + + "' with value [" + value + "] due to error dispatch: " + ex.getMessage()); + } + } + else { + throw new IllegalStateException("Invalid locale cookie '" + cookieName + + "' with value [" + value + "]: " + ex.getMessage()); + } + } + if (logger.isDebugEnabled()) { + logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale + + "'" + (timeZone != null ? " and time zone '" + timeZone.getID() + "'" : "")); } } - if (logger.isDebugEnabled()) { - logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale + - "'" + (timeZone != null ? " and time zone '" + timeZone.getID() + "'" : "")); - } } + request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, (locale != null ? locale : determineDefaultLocale(request))); request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME, diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/theme/CookieThemeResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/theme/CookieThemeResolver.java index 77f3bb4cb37..2bec033b15d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/theme/CookieThemeResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/theme/CookieThemeResolver.java @@ -88,11 +88,14 @@ public class CookieThemeResolver extends CookieGenerator implements ThemeResolve } // Retrieve cookie value from request. - Cookie cookie = WebUtils.getCookie(request, getCookieName()); - if (cookie != null) { - String value = cookie.getValue(); - if (StringUtils.hasText(value)) { - themeName = value; + String cookieName = getCookieName(); + if (cookieName != null) { + Cookie cookie = WebUtils.getCookie(request, cookieName); + if (cookie != null) { + String value = cookie.getValue(); + if (StringUtils.hasText(value)) { + themeName = value; + } } }