Nullability fine-tuning around bean properties

Issue: SPR-15720
Issue: SPR-15792
This commit is contained in:
Juergen Hoeller
2017-07-19 11:43:58 +02:00
parent 06fc092be2
commit 9fc4fb10b0
31 changed files with 243 additions and 206 deletions

View File

@@ -126,7 +126,7 @@ public class FieldRetrievingFactoryBean
* @see #setTargetObject * @see #setTargetObject
*/ */
public void setTargetField(@Nullable String targetField) { public void setTargetField(@Nullable String targetField) {
this.targetField = StringUtils.trimAllWhitespace(targetField); this.targetField = (targetField != null ? StringUtils.trimAllWhitespace(targetField) : null);
} }
/** /**

View File

@@ -81,8 +81,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private final Map<CacheOperationCacheKey, CacheOperationMetadata> metadataCache = private final Map<CacheOperationCacheKey, CacheOperationMetadata> metadataCache = new ConcurrentHashMap<>(1024);
new ConcurrentHashMap<>(1024);
private final CacheOperationExpressionEvaluator evaluator = new CacheOperationExpressionEvaluator(); private final CacheOperationExpressionEvaluator evaluator = new CacheOperationExpressionEvaluator();
@@ -186,6 +185,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
public void afterSingletonsInstantiated() { public void afterSingletonsInstantiated() {
if (getCacheResolver() == null) { if (getCacheResolver() == null) {
// Lazily initialize cache resolver via default cache manager... // Lazily initialize cache resolver via default cache manager...
Assert.state(this.beanFactory != null, "CacheResolver or BeanFactory must be set on cache aspect");
try { try {
setCacheManager(this.beanFactory.getBean(CacheManager.class)); setCacheManager(this.beanFactory.getBean(CacheManager.class));
} }
@@ -289,6 +289,10 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
* @see CacheOperation#cacheResolver * @see CacheOperation#cacheResolver
*/ */
protected <T> T getBean(String beanName, Class<T> expectedType) { protected <T> T getBean(String beanName, Class<T> 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); return BeanFactoryAnnotationUtils.qualifiedBeanOfType(this.beanFactory, expectedType, beanName);
} }

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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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<String> basenameSet = new LinkedHashSet<>(4); private final Set<String> basenameSet = new LinkedHashSet<>(4);
@Nullable
private String defaultEncoding; private String defaultEncoding;
private boolean fallbackToSystemLocale = true; private boolean fallbackToSystemLocale = true;

View File

@@ -535,9 +535,6 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
} }
private void assertValidators(Validator... validators) { private void assertValidators(Validator... validators) {
if (validators == null) {
return;
}
for (Validator validator : validators) { for (Validator validator : validators) {
if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) { if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) {
throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget()); throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget());

View File

@@ -41,6 +41,7 @@ public class CustomizableThreadCreator implements Serializable {
private boolean daemon = false; private boolean daemon = false;
@Nullable
private ThreadGroup threadGroup; private ThreadGroup threadGroup;
private final AtomicInteger threadCount = new AtomicInteger(0); private final AtomicInteger threadCount = new AtomicInteger(0);

View File

@@ -132,7 +132,7 @@ public class ListenableFutureCallbackRegistry<T> {
* added callbacks with the given result. * added callbacks with the given result.
* @param result the result to trigger the callbacks with * @param result the result to trigger the callbacks with
*/ */
public void success(T result) { public void success(@Nullable T result) {
synchronized (this.mutex) { synchronized (this.mutex) {
this.state = State.SUCCESS; this.state = State.SUCCESS;
this.result = result; this.result = result;

View File

@@ -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}. * handler. The property name for a lexical handler is {@code http://xml.org/sax/properties/lexical-handler}.
*/ */
@Override @Override
@Nullable
public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException { public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { if ("http://xml.org/sax/properties/lexical-handler".equals(name)) {
return this.lexicalHandler; return this.lexicalHandler;

View File

@@ -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 * Create a ReturnResultSetParameter/SqlOutParameter depending on the support provided
* by the JDBC driver used for the database in use. * by the JDBC driver used for the database in use.
@@ -252,13 +265,13 @@ public class CallMetaDataContext {
* @return the appropriate SqlParameter * @return the appropriate SqlParameter
*/ */
public SqlParameter createReturnResultSetParameter(String parameterName, RowMapper<?> rowMapper) { public SqlParameter createReturnResultSetParameter(String parameterName, RowMapper<?> rowMapper) {
Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); CallMetaDataProvider provider = obtainMetaDataProvider();
if (this.metaDataProvider.isReturnResultSetSupported()) { if (provider.isReturnResultSetSupported()) {
return new SqlReturnResultSet(parameterName, rowMapper); return new SqlReturnResultSet(parameterName, rowMapper);
} }
else { else {
if (this.metaDataProvider.isRefCursorSupported()) { if (provider.isRefCursorSupported()) {
return new SqlOutParameter(parameterName, this.metaDataProvider.getRefCursorSqlType(), rowMapper); return new SqlOutParameter(parameterName, provider.getRefCursorSqlType(), rowMapper);
} }
else { else {
throw new InvalidDataAccessApiUsageException("Return of a ResultSet from a stored procedure is not supported."); throw new InvalidDataAccessApiUsageException("Return of a ResultSet from a stored procedure is not supported.");
@@ -290,14 +303,6 @@ public class CallMetaDataContext {
return this.callParameters; 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, * 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 * 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. * Reconcile the provided parameters with available metadata and add new ones where appropriate.
*/ */
protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) { protected List<SqlParameter> reconcileParameters(List<SqlParameter> parameters) {
Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); CallMetaDataProvider provider = obtainMetaDataProvider();
final List<SqlParameter> declaredReturnParams = new ArrayList<>(); final List<SqlParameter> declaredReturnParams = new ArrayList<>();
final Map<String, SqlParameter> declaredParams = new LinkedHashMap<>(); final Map<String, SqlParameter> declaredParams = new LinkedHashMap<>();
@@ -321,7 +326,7 @@ public class CallMetaDataContext {
List<String> metaDataParamNames = new ArrayList<>(); List<String> metaDataParamNames = new ArrayList<>();
// Get the names of the meta data parameters // Get the names of the meta data parameters
for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { for (CallParameterMetaData meta : provider.getCallParameterMetaData()) {
if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) { if (meta.getParameterType() != DatabaseMetaData.procedureColumnReturn) {
metaDataParamNames.add(lowerCase(meta.getParameterName())); metaDataParamNames.add(lowerCase(meta.getParameterName()));
} }
@@ -338,7 +343,7 @@ public class CallMetaDataContext {
throw new IllegalArgumentException("Anonymous parameters not supported for calls - " + throw new IllegalArgumentException("Anonymous parameters not supported for calls - " +
"please specify a name for the parameter of SQL type " + param.getSqlType()); "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); declaredParams.put(paramNameToMatch, param);
if (param instanceof SqlOutParameter) { if (param instanceof SqlOutParameter) {
outParamNames.add(paramName); outParamNames.add(paramName);
@@ -360,24 +365,23 @@ public class CallMetaDataContext {
List<SqlParameter> workParams = new ArrayList<>(); List<SqlParameter> workParams = new ArrayList<>();
workParams.addAll(declaredReturnParams); workParams.addAll(declaredReturnParams);
if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { if (!provider.isProcedureColumnMetaDataUsed()) {
workParams.addAll(declaredParams.values()); workParams.addAll(declaredParams.values());
return workParams; return workParams;
} }
Map<String, String> limitedInParamNamesMap = new HashMap<>(this.limitedInParameterNames.size()); Map<String, String> limitedInParamNamesMap = new HashMap<>(this.limitedInParameterNames.size());
for (String limitedParamName : this.limitedInParameterNames) { for (String limitedParamName : this.limitedInParameterNames) {
limitedInParamNamesMap.put( limitedInParamNamesMap.put(lowerCase(provider.parameterNameToUse(limitedParamName)), limitedParamName);
lowerCase(this.metaDataProvider.parameterNameToUse(limitedParamName)), limitedParamName);
} }
for (CallParameterMetaData meta : this.metaDataProvider.getCallParameterMetaData()) { for (CallParameterMetaData meta : provider.getCallParameterMetaData()) {
String paramName = meta.getParameterName(); String paramName = meta.getParameterName();
String paramNameToCheck = null; String paramNameToCheck = null;
if (paramName != 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) || if (declaredParams.containsKey(paramNameToCheck) ||
(meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) { (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn && returnDeclared)) {
SqlParameter param; SqlParameter param;
@@ -409,7 +413,7 @@ public class CallMetaDataContext {
else { else {
if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) { if (meta.getParameterType() == DatabaseMetaData.procedureColumnReturn) {
if (!isFunction() && !isReturnValueRequired() && paramName != null && if (!isFunction() && !isReturnValueRequired() && paramName != null &&
this.metaDataProvider.byPassReturnParameter(paramName)) { provider.byPassReturnParameter(paramName)) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Bypassing metadata return parameter for '" + paramName + "'"); logger.debug("Bypassing metadata return parameter for '" + paramName + "'");
} }
@@ -417,7 +421,7 @@ public class CallMetaDataContext {
else { else {
String returnNameToUse = String returnNameToUse =
(StringUtils.hasLength(paramNameToUse) ? paramNameToUse : getFunctionReturnName()); (StringUtils.hasLength(paramNameToUse) ? paramNameToUse : getFunctionReturnName());
workParams.add(this.metaDataProvider.createDefaultOutParameter(returnNameToUse, meta)); workParams.add(provider.createDefaultOutParameter(returnNameToUse, meta));
if (isFunction()) { if (isFunction()) {
setFunctionReturnName(returnNameToUse); setFunctionReturnName(returnNameToUse);
outParamNames.add(returnNameToUse); outParamNames.add(returnNameToUse);
@@ -432,14 +436,14 @@ public class CallMetaDataContext {
paramNameToUse = ""; paramNameToUse = "";
} }
if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) { if (meta.getParameterType() == DatabaseMetaData.procedureColumnOut) {
workParams.add(this.metaDataProvider.createDefaultOutParameter(paramNameToUse, meta)); workParams.add(provider.createDefaultOutParameter(paramNameToUse, meta));
outParamNames.add(paramNameToUse); outParamNames.add(paramNameToUse);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata out parameter for '" + paramNameToUse + "'"); logger.debug("Added metadata out parameter for '" + paramNameToUse + "'");
} }
} }
else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) { else if (meta.getParameterType() == DatabaseMetaData.procedureColumnInOut) {
workParams.add(this.metaDataProvider.createDefaultInOutParameter(paramNameToUse, meta)); workParams.add(provider.createDefaultInOutParameter(paramNameToUse, meta));
outParamNames.add(paramNameToUse); outParamNames.add(paramNameToUse);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'"); logger.debug("Added metadata in out parameter for '" + paramNameToUse + "'");
@@ -448,7 +452,7 @@ public class CallMetaDataContext {
else { else {
if (this.limitedInParameterNames.isEmpty() || if (this.limitedInParameterNames.isEmpty() ||
limitedInParamNamesMap.containsKey(lowerCase(paramNameToUse))) { limitedInParamNamesMap.containsKey(lowerCase(paramNameToUse))) {
workParams.add(this.metaDataProvider.createDefaultInParameter(paramNameToUse, meta)); workParams.add(provider.createDefaultInParameter(paramNameToUse, meta));
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Added metadata in parameter for '" + paramNameToUse + "'"); 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 * @return a Map containing the matched parameter names with the value taken from the input
*/ */
public Map<String, Object> matchInParameterValuesWithCallParameters(SqlParameterSource parameterSource) { public Map<String, Object> matchInParameterValuesWithCallParameters(SqlParameterSource parameterSource) {
Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available");
// For parameter source lookups we need to provide case-insensitive lookup support // For parameter source lookups we need to provide case-insensitive lookup support
// since the database metadata is not necessarily providing case sensitive parameter names. // since the database metadata is not necessarily providing case sensitive parameter names.
Map<String, String> caseInsensitiveParameterNames = Map<String, String> caseInsensitiveParameterNames =
@@ -485,7 +487,7 @@ public class CallMetaDataContext {
for (SqlParameter parameter : this.callParameters) { for (SqlParameter parameter : this.callParameters) {
if (parameter.isInputValueProvided()) { if (parameter.isInputValueProvided()) {
String parameterName = parameter.getName(); String parameterName = parameter.getName();
String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); String parameterNameToMatch = obtainMetaDataProvider().parameterNameToUse(parameterName);
if (parameterNameToMatch != null) { if (parameterNameToMatch != null) {
callParameterNames.put(parameterNameToMatch.toLowerCase(), parameterName); 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 * @return a Map containing the matched parameter names with the value taken from the input
*/ */
public Map<String, ?> matchInParameterValuesWithCallParameters(Map<String, ?> inParameters) { public Map<String, ?> matchInParameterValuesWithCallParameters(Map<String, ?> inParameters) {
Assert.state(this.metaDataProvider != null, "No CallMetaDataProvider available"); CallMetaDataProvider provider = obtainMetaDataProvider();
if (!this.metaDataProvider.isProcedureColumnMetaDataUsed()) { if (!provider.isProcedureColumnMetaDataUsed()) {
return inParameters; return inParameters;
} }
@@ -547,7 +549,7 @@ public class CallMetaDataContext {
for (SqlParameter parameter : this.callParameters) { for (SqlParameter parameter : this.callParameters) {
if (parameter.isInputValueProvided()) { if (parameter.isInputValueProvided()) {
String parameterName = parameter.getName(); String parameterName = parameter.getName();
String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); String parameterNameToMatch = provider.parameterNameToUse(parameterName);
if (parameterNameToMatch != null) { if (parameterNameToMatch != null) {
callParameterNames.put(parameterNameToMatch.toLowerCase(), parameterName); callParameterNames.put(parameterNameToMatch.toLowerCase(), parameterName);
} }
@@ -556,7 +558,7 @@ public class CallMetaDataContext {
Map<String, Object> matchedParameters = new HashMap<>(inParameters.size()); Map<String, Object> matchedParameters = new HashMap<>(inParameters.size());
for (String parameterName : inParameters.keySet()) { for (String parameterName : inParameters.keySet()) {
String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); String parameterNameToMatch = provider.parameterNameToUse(parameterName);
String callParameterName = callParameterNames.get(lowerCase(parameterNameToMatch)); String callParameterName = callParameterNames.get(lowerCase(parameterNameToMatch));
if (callParameterName == null) { if (callParameterName == null) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@@ -577,7 +579,7 @@ public class CallMetaDataContext {
if (matchedParameters.size() < callParameterNames.size()) { if (matchedParameters.size() < callParameterNames.size()) {
for (String parameterName : callParameterNames.keySet()) { for (String parameterName : callParameterNames.keySet()) {
String parameterNameToMatch = this.metaDataProvider.parameterNameToUse(parameterName); String parameterNameToMatch = provider.parameterNameToUse(parameterName);
String callParameterName = callParameterNames.get(lowerCase(parameterNameToMatch)); String callParameterName = callParameterNames.get(lowerCase(parameterNameToMatch));
if (!matchedParameters.containsKey(callParameterName)) { if (!matchedParameters.containsKey(callParameterName)) {
logger.warn("Unable to locate the corresponding parameter value for '" + parameterName + logger.warn("Unable to locate the corresponding parameter value for '" + parameterName +

View File

@@ -33,6 +33,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils; import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.jdbc.support.JdbcUtils; import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/** /**
* Class to manage context metadata used for the configuration * Class to manage context metadata used for the configuration
@@ -47,13 +48,16 @@ public class TableMetaDataContext {
/** Logger available to subclasses */ /** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
/** name of table for this context **/ /** Name of table for this context */
@Nullable
private String tableName; private String tableName;
/** name of catalog for this context **/ /** Name of catalog for this context */
@Nullable
private String catalogName; private String catalogName;
/** name of schema for this context **/ /** Name of schema for this context */
@Nullable
private String schemaName; private String schemaName;
/** List of columns objects to be used in this context */ /** List of columns objects to be used in this context */
@@ -66,6 +70,7 @@ public class TableMetaDataContext {
private boolean overrideIncludeSynonymsDefault = false; private boolean overrideIncludeSynonymsDefault = false;
/** the provider of table meta data */ /** the provider of table meta data */
@Nullable
private TableMetaDataProvider metaDataProvider; private TableMetaDataProvider metaDataProvider;
/** are we using generated key columns */ /** are we using generated key columns */
@@ -153,41 +158,6 @@ public class TableMetaDataContext {
return this.tableColumns; 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. * Process the current meta data with the provided configuration options.
@@ -200,6 +170,11 @@ public class TableMetaDataContext {
this.tableColumns = reconcileColumnsToUse(declaredColumns, generatedKeyNames); 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. * Compare columns created from metadata with declared columns and return a reconciled list.
* @param declaredColumns declared column names * @param declaredColumns declared column names
@@ -217,7 +192,7 @@ public class TableMetaDataContext {
keys.add(key.toUpperCase()); keys.add(key.toUpperCase());
} }
List<String> columns = new ArrayList<>(); List<String> columns = new ArrayList<>();
for (TableParameterMetaData meta : metaDataProvider.getTableParameterMetaData()) { for (TableParameterMetaData meta : obtainMetaDataProvider().getTableParameterMetaData()) {
if (!keys.contains(meta.getParameterName().toUpperCase())) { if (!keys.contains(meta.getParameterName().toUpperCase())) {
columns.add(meta.getParameterName()); columns.add(meta.getParameterName());
} }
@@ -336,7 +311,7 @@ public class TableMetaDataContext {
*/ */
public int[] createInsertTypes() { public int[] createInsertTypes() {
int[] types = new int[getTableColumns().size()]; int[] types = new int[getTableColumns().size()];
List<TableParameterMetaData> parameters = this.metaDataProvider.getTableParameterMetaData(); List<TableParameterMetaData> parameters = obtainMetaDataProvider().getTableParameterMetaData();
Map<String, TableParameterMetaData> parameterMap = Map<String, TableParameterMetaData> parameterMap =
new LinkedHashMap<>(parameters.size()); new LinkedHashMap<>(parameters.size());
for (TableParameterMetaData tpmd : parameters) { for (TableParameterMetaData tpmd : parameters) {
@@ -361,4 +336,40 @@ public class TableMetaDataContext {
return types; 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();
}
} }

View File

@@ -21,7 +21,6 @@ import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/** /**
* Abstract base class for JDBC {@link javax.sql.DataSource} implementations * 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) * @see java.sql.Driver#connect(String, java.util.Properties)
*/ */
public void setUrl(@Nullable String url) { public void setUrl(@Nullable String url) {
Assert.hasText(url, "Property 'url' must not be empty"); this.url = (url != null ? url.trim() : null);
this.url = url.trim();
} }
/** /**

View File

@@ -33,6 +33,7 @@ public class CustomSQLErrorCodesTranslation {
private String[] errorCodes = new String[0]; private String[] errorCodes = new String[0];
@Nullable
private Class<?> exceptionClass; private Class<?> exceptionClass;

View File

@@ -79,11 +79,11 @@ import org.springframework.util.Assert;
public class TransactionAwareConnectionFactoryProxy public class TransactionAwareConnectionFactoryProxy
implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory { implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory {
private boolean synchedLocalTransactionAllowed = false;
@Nullable @Nullable
private ConnectionFactory targetConnectionFactory; private ConnectionFactory targetConnectionFactory;
private boolean synchedLocalTransactionAllowed = false;
/** /**
* Create a new TransactionAwareConnectionFactoryProxy. * Create a new TransactionAwareConnectionFactoryProxy.
@@ -103,16 +103,18 @@ public class TransactionAwareConnectionFactoryProxy
/** /**
* Set the target ConnectionFactory that this ConnectionFactory should delegate to. * 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; this.targetConnectionFactory = targetConnectionFactory;
} }
/** /**
* Return the target ConnectionFactory that this ConnectionFactory should delegate to. * Return the target ConnectionFactory that this ConnectionFactory should delegate to.
*/ */
@Nullable
protected ConnectionFactory getTargetConnectionFactory() { 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 @Override
public Connection createConnection() throws JMSException { public Connection createConnection() throws JMSException {
Connection targetConnection = this.targetConnectionFactory.createConnection(); Connection targetConnection = getTargetConnectionFactory().createConnection();
return getTransactionAwareConnectionProxy(targetConnection); return getTransactionAwareConnectionProxy(targetConnection);
} }
@Override @Override
public Connection createConnection(String username, String password) throws JMSException { public Connection createConnection(String username, String password) throws JMSException {
Connection targetConnection = obtainTargetConnectionFactory().createConnection(username, password); Connection targetConnection = getTargetConnectionFactory().createConnection(username, password);
return getTransactionAwareConnectionProxy(targetConnection); return getTransactionAwareConnectionProxy(targetConnection);
} }
@Override @Override
public QueueConnection createQueueConnection() throws JMSException { public QueueConnection createQueueConnection() throws JMSException {
ConnectionFactory target = obtainTargetConnectionFactory(); ConnectionFactory target = getTargetConnectionFactory();
if (!(target instanceof QueueConnectionFactory)) { if (!(target instanceof QueueConnectionFactory)) {
throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory"); throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory");
} }
@@ -163,7 +165,7 @@ public class TransactionAwareConnectionFactoryProxy
@Override @Override
public QueueConnection createQueueConnection(String username, String password) throws JMSException { public QueueConnection createQueueConnection(String username, String password) throws JMSException {
ConnectionFactory target = obtainTargetConnectionFactory(); ConnectionFactory target = getTargetConnectionFactory();
if (!(target instanceof QueueConnectionFactory)) { if (!(target instanceof QueueConnectionFactory)) {
throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory"); throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no QueueConnectionFactory");
} }
@@ -173,7 +175,7 @@ public class TransactionAwareConnectionFactoryProxy
@Override @Override
public TopicConnection createTopicConnection() throws JMSException { public TopicConnection createTopicConnection() throws JMSException {
ConnectionFactory target = obtainTargetConnectionFactory(); ConnectionFactory target = getTargetConnectionFactory();
if (!(target instanceof TopicConnectionFactory)) { if (!(target instanceof TopicConnectionFactory)) {
throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory"); throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory");
} }
@@ -183,7 +185,7 @@ public class TransactionAwareConnectionFactoryProxy
@Override @Override
public TopicConnection createTopicConnection(String username, String password) throws JMSException { public TopicConnection createTopicConnection(String username, String password) throws JMSException {
ConnectionFactory target = obtainTargetConnectionFactory(); ConnectionFactory target = getTargetConnectionFactory();
if (!(target instanceof TopicConnectionFactory)) { if (!(target instanceof TopicConnectionFactory)) {
throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory"); throw new javax.jms.IllegalStateException("'targetConnectionFactory' is no TopicConnectionFactory");
} }
@@ -193,28 +195,22 @@ public class TransactionAwareConnectionFactoryProxy
@Override @Override
public JMSContext createContext() { public JMSContext createContext() {
return obtainTargetConnectionFactory().createContext(); return getTargetConnectionFactory().createContext();
} }
@Override @Override
public JMSContext createContext(String userName, String password) { public JMSContext createContext(String userName, String password) {
return obtainTargetConnectionFactory().createContext(userName, password); return getTargetConnectionFactory().createContext(userName, password);
} }
@Override @Override
public JMSContext createContext(String userName, String password, int sessionMode) { public JMSContext createContext(String userName, String password, int sessionMode) {
return obtainTargetConnectionFactory().createContext(userName, password, sessionMode); return getTargetConnectionFactory().createContext(userName, password, sessionMode);
} }
@Override @Override
public JMSContext createContext(int sessionMode) { public JMSContext createContext(int sessionMode) {
return obtainTargetConnectionFactory().createContext(sessionMode); return getTargetConnectionFactory().createContext(sessionMode);
}
private ConnectionFactory obtainTargetConnectionFactory() {
ConnectionFactory target = getTargetConnectionFactory();
Assert.state(target != null, "'targetConnectionFactory' is required");
return target;
} }
@@ -265,14 +261,14 @@ public class TransactionAwareConnectionFactoryProxy
} }
else if (Session.class == method.getReturnType()) { else if (Session.class == method.getReturnType()) {
Session session = ConnectionFactoryUtils.getTransactionalSession( Session session = ConnectionFactoryUtils.getTransactionalSession(
obtainTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed()); getTargetConnectionFactory(), this.target, isSynchedLocalTransactionAllowed());
if (session != null) { if (session != null) {
return getCloseSuppressingSessionProxy(session); return getCloseSuppressingSessionProxy(session);
} }
} }
else if (QueueSession.class == method.getReturnType()) { else if (QueueSession.class == method.getReturnType()) {
QueueSession session = ConnectionFactoryUtils.getTransactionalQueueSession( QueueSession session = ConnectionFactoryUtils.getTransactionalQueueSession(
(QueueConnectionFactory) obtainTargetConnectionFactory(), (QueueConnection) this.target, (QueueConnectionFactory) getTargetConnectionFactory(), (QueueConnection) this.target,
isSynchedLocalTransactionAllowed()); isSynchedLocalTransactionAllowed());
if (session != null) { if (session != null) {
return getCloseSuppressingSessionProxy(session); return getCloseSuppressingSessionProxy(session);
@@ -280,7 +276,7 @@ public class TransactionAwareConnectionFactoryProxy
} }
else if (TopicSession.class == method.getReturnType()) { else if (TopicSession.class == method.getReturnType()) {
TopicSession session = ConnectionFactoryUtils.getTransactionalTopicSession( TopicSession session = ConnectionFactoryUtils.getTransactionalTopicSession(
(TopicConnectionFactory) obtainTargetConnectionFactory(), (TopicConnection) this.target, (TopicConnectionFactory) getTargetConnectionFactory(), (TopicConnection) this.target,
isSynchedLocalTransactionAllowed()); isSynchedLocalTransactionAllowed());
if (session != null) { if (session != null) {
return getCloseSuppressingSessionProxy(session); return getCloseSuppressingSessionProxy(session);

View File

@@ -95,6 +95,7 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
@Nullable @Nullable
private Object defaultDestination; private Object defaultDestination;
@Nullable
private MessageConverter messageConverter; private MessageConverter messageConverter;
@@ -228,13 +229,14 @@ public class JmsTemplate extends JmsDestinationAccessor implements JmsOperations
* @see #receiveAndConvert * @see #receiveAndConvert
* @see org.springframework.jms.support.converter.SimpleMessageConverter * @see org.springframework.jms.support.converter.SimpleMessageConverter
*/ */
public void setMessageConverter(MessageConverter messageConverter) { public void setMessageConverter(@Nullable MessageConverter messageConverter) {
this.messageConverter = messageConverter; this.messageConverter = messageConverter;
} }
/** /**
* Return the message converter for this template. * Return the message converter for this template.
*/ */
@Nullable
public MessageConverter getMessageConverter() { public MessageConverter getMessageConverter() {
return this.messageConverter; return this.messageConverter;
} }

View File

@@ -65,6 +65,7 @@ public abstract class AbstractAdaptableMessageListener
private DestinationResolver destinationResolver = new DynamicDestinationResolver(); private DestinationResolver destinationResolver = new DynamicDestinationResolver();
@Nullable
private MessageConverter messageConverter = new SimpleMessageConverter(); private MessageConverter messageConverter = new SimpleMessageConverter();
private final MessagingMessageConverterAdapter messagingMessageConverter = new MessagingMessageConverterAdapter(); private final MessagingMessageConverterAdapter messagingMessageConverter = new MessagingMessageConverterAdapter();

View File

@@ -232,11 +232,15 @@ public abstract class AbstractMethodMessageHandler<T>
this.returnValueHandlers.addHandlers(initReturnValueHandlers()); 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)) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null; Class<?> beanType = null;
try { try {
beanType = this.applicationContext.getType(beanName); beanType = context.getType(beanName);
} }
catch (Throwable ex) { catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it. // An unresolvable bean type, probably from a lazy bean - let's ignore it.
@@ -279,8 +283,15 @@ public abstract class AbstractMethodMessageHandler<T>
* @param handler the handler to check, either an instance of a Spring bean name * @param handler the handler to check, either an instance of a Spring bean name
*/ */
protected final void detectHandlerMethods(final Object handler) { protected final void detectHandlerMethods(final Object handler) {
Class<?> handlerType = (handler instanceof String ? Class<?> handlerType;
this.applicationContext.getType((String) handler) : handler.getClass()); 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) { if (handlerType != null) {
final Class<?> userType = ClassUtils.getUserClass(handlerType); final Class<?> userType = ClassUtils.getUserClass(handlerType);
@@ -338,9 +349,10 @@ public abstract class AbstractMethodMessageHandler<T>
protected HandlerMethod createHandlerMethod(Object handler, Method method) { protected HandlerMethod createHandlerMethod(Object handler, Method method) {
HandlerMethod handlerMethod; HandlerMethod handlerMethod;
if (handler instanceof String) { if (handler instanceof String) {
ApplicationContext context = getApplicationContext();
Assert.state(context != null, "ApplicationContext is required for resolving handler bean names");
String beanName = (String) handler; String beanName = (String) handler;
handlerMethod = new HandlerMethod(beanName, handlerMethod = new HandlerMethod(beanName, context.getAutowireCapableBeanFactory(), method);
this.applicationContext.getAutowireCapableBeanFactory(), method);
} }
else { else {
handlerMethod = new HandlerMethod(handler, method); handlerMethod = new HandlerMethod(handler, method);
@@ -645,7 +657,7 @@ public abstract class AbstractMethodMessageHandler<T>
} }
@Override @Override
public void onSuccess(Object result) { public void onSuccess(@Nullable Object result) {
try { try {
MethodParameter returnType = this.handlerMethod.getAsyncReturnValueType(result); MethodParameter returnType = this.handlerMethod.getAsyncReturnValueType(result);
returnValueHandlers.handleReturnValue(result, returnType, this.message); returnValueHandlers.handleReturnValue(result, returnType, this.message);

View File

@@ -252,7 +252,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
} }
MethodParameter getAsyncReturnValueType(Object returnValue) { MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
return new AsyncResultMethodParameter(returnValue); return new AsyncResultMethodParameter(returnValue);
} }
@@ -264,7 +264,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private final ResolvableType returnType; private final ResolvableType returnType;
public AsyncResultMethodParameter(Object returnValue) { public AsyncResultMethodParameter(@Nullable Object returnValue) {
super(-1); super(-1);
this.returnValue = returnValue; this.returnValue = returnValue;
this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric(); this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric();

View File

@@ -54,6 +54,7 @@ public class SimpMessagingTemplate extends AbstractMessageSendingTemplate<String
private volatile long sendTimeout = -1; private volatile long sendTimeout = -1;
@Nullable
private MessageHeaderInitializer headerInitializer; private MessageHeaderInitializer headerInitializer;

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.SmartLifecycle; import org.springframework.context.SmartLifecycle;
@@ -305,8 +306,9 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan
protected List<HandlerMethodArgumentResolver> initArgumentResolvers() { protected List<HandlerMethodArgumentResolver> initArgumentResolvers() {
ConfigurableBeanFactory beanFactory = (getApplicationContext() instanceof ConfigurableApplicationContext ? ApplicationContext context = getApplicationContext();
((ConfigurableApplicationContext) getApplicationContext()).getBeanFactory() : null); ConfigurableBeanFactory beanFactory = (context instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) context).getBeanFactory() : null);
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

View File

@@ -16,8 +16,6 @@
package org.springframework.messaging.support; package org.springframework.messaging.support;
import java.util.UUID;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessageHeaders;
import org.springframework.util.IdGenerator; import org.springframework.util.IdGenerator;
@@ -31,6 +29,10 @@ import org.springframework.util.IdGenerator;
*/ */
public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitializer { public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitializer {
private static final IdGenerator ID_VALUE_NONE_GENERATOR = () -> MessageHeaders.ID_VALUE_NONE;
@Nullable
private IdGenerator idGenerator; private IdGenerator idGenerator;
private boolean enableTimestamp; private boolean enableTimestamp;
@@ -41,20 +43,12 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial
* instances with. * instances with.
* <p>By default this property is set to {@code null} in which case the default * <p>By default this property is set to {@code null} in which case the default
* IdGenerator of {@link org.springframework.messaging.MessageHeaders} is used. * IdGenerator of {@link org.springframework.messaging.MessageHeaders} is used.
* <p>To have no id's generated at all, see {@link #setDisableIdGeneration()}. * <p>To have no ids generated at all, see {@link #setDisableIdGeneration()}.
*/ */
public void setIdGenerator(@Nullable IdGenerator idGenerator) { public void setIdGenerator(@Nullable IdGenerator idGenerator) {
this.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. * Return the configured {@code IdGenerator}, if any.
*/ */
@@ -63,6 +57,14 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial
return this.idGenerator; 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 * Whether to enable the automatic addition of the
* {@link org.springframework.messaging.MessageHeaders#TIMESTAMP} header on * {@link org.springframework.messaging.MessageHeaders#TIMESTAMP} header on
@@ -90,12 +92,4 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial
headerAccessor.setEnableTimestamp(isEnableTimestamp()); headerAccessor.setEnableTimestamp(isEnableTimestamp());
} }
private static final IdGenerator ID_VALUE_NONE_GENERATOR = new IdGenerator() {
@Override
public UUID generateId() {
return MessageHeaders.ID_VALUE_NONE;
}
};
} }

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.TimeoutException;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoProcessor; import reactor.core.publisher.MonoProcessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.concurrent.FailureCallback; import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFuture;
@@ -67,12 +68,14 @@ abstract class AbstractMonoToListenableFutureAdapter<S, T> implements Listenable
@Override @Override
@Nullable
public T get() throws InterruptedException { public T get() throws InterruptedException {
S result = this.monoProcessor.block(); S result = this.monoProcessor.block();
return adapt(result); return adapt(result);
} }
@Override @Override
@Nullable
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
Assert.notNull(unit, "TimeUnit must not be null"); Assert.notNull(unit, "TimeUnit must not be null");
Duration duration = Duration.ofMillis(TimeUnit.MILLISECONDS.convert(timeout, unit)); Duration duration = Duration.ofMillis(TimeUnit.MILLISECONDS.convert(timeout, unit));
@@ -111,6 +114,7 @@ abstract class AbstractMonoToListenableFutureAdapter<S, T> implements Listenable
} }
protected abstract T adapt(S result); @Nullable
protected abstract T adapt(@Nullable S result);
} }

View File

@@ -18,6 +18,8 @@ package org.springframework.messaging.tcp.reactor;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.lang.Nullable;
/** /**
* A Mono-to-ListenableFuture adapter where the source and the target from * A Mono-to-ListenableFuture adapter where the source and the target from
* the Promise and the ListenableFuture respectively are of the same type. * the Promise and the ListenableFuture respectively are of the same type.
@@ -33,7 +35,7 @@ class MonoToListenableFutureAdapter<T> extends AbstractMonoToListenableFutureAda
} }
@Override @Override
protected T adapt(T result) { protected T adapt(@Nullable T result) {
return result; return result;
} }

View File

@@ -36,6 +36,7 @@ public abstract class AbstractJpaVendorAdapter implements JpaVendorAdapter {
private Database database = Database.DEFAULT; private Database database = Database.DEFAULT;
@Nullable
private String databasePlatform; private String databasePlatform;
private boolean generateDdl = false; 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: * 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 * 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; this.database = database;
} }
/** /**
* Return the target database to operate on. * Return the target database to operate on.
*/ */
@Nullable
protected Database getDatabase() { protected Database getDatabase() {
return this.database; return this.database;
} }

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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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) { if (getDatabasePlatform() != null) {
jpaProperties.put(PersistenceUnitProperties.TARGET_DATABASE, getDatabasePlatform()); jpaProperties.put(PersistenceUnitProperties.TARGET_DATABASE, getDatabasePlatform());
} }
else if (getDatabase() != null) { else {
String targetDatabase = determineTargetDatabaseName(getDatabase()); String targetDatabase = determineTargetDatabaseName(getDatabase());
if (targetDatabase != null) { if (targetDatabase != null) {
jpaProperties.put(PersistenceUnitProperties.TARGET_DATABASE, targetDatabase); jpaProperties.put(PersistenceUnitProperties.TARGET_DATABASE, targetDatabase);

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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.HashMap;
import java.util.Map; import java.util.Map;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceProvider;
@@ -117,7 +116,7 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
if (getDatabasePlatform() != null) { if (getDatabasePlatform() != null) {
jpaProperties.put(AvailableSettings.DIALECT, getDatabasePlatform()); jpaProperties.put(AvailableSettings.DIALECT, getDatabasePlatform());
} }
else if (getDatabase() != null) { else {
Class<?> databaseDialectClass = determineDatabaseDialectClass(getDatabase()); Class<?> databaseDialectClass = determineDatabaseDialectClass(getDatabase());
if (databaseDialectClass != null) { if (databaseDialectClass != null) {
jpaProperties.put(AvailableSettings.DIALECT, databaseDialectClass.getName()); jpaProperties.put(AvailableSettings.DIALECT, databaseDialectClass.getName());

View File

@@ -54,6 +54,7 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
private List<MediaType> supportedMediaTypes = Collections.emptyList(); private List<MediaType> supportedMediaTypes = Collections.emptyList();
@Nullable
private Charset defaultCharset; private Charset defaultCharset;

View File

@@ -75,8 +75,10 @@ public class WebDataBinder extends DataBinder {
*/ */
public static final String DEFAULT_FIELD_DEFAULT_PREFIX = "!"; public static final String DEFAULT_FIELD_DEFAULT_PREFIX = "!";
@Nullable
private String fieldMarkerPrefix = DEFAULT_FIELD_MARKER_PREFIX; private String fieldMarkerPrefix = DEFAULT_FIELD_MARKER_PREFIX;
@Nullable
private String fieldDefaultPrefix = DEFAULT_FIELD_DEFAULT_PREFIX; private String fieldDefaultPrefix = DEFAULT_FIELD_DEFAULT_PREFIX;
private boolean bindEmptyMultipartFiles = true; private boolean bindEmptyMultipartFiles = true;
@@ -124,13 +126,14 @@ public class WebDataBinder extends DataBinder {
* detect an empty field and automatically reset its value. * detect an empty field and automatically reset its value.
* @see #DEFAULT_FIELD_MARKER_PREFIX * @see #DEFAULT_FIELD_MARKER_PREFIX
*/ */
public void setFieldMarkerPrefix(String fieldMarkerPrefix) { public void setFieldMarkerPrefix(@Nullable String fieldMarkerPrefix) {
this.fieldMarkerPrefix = fieldMarkerPrefix; this.fieldMarkerPrefix = fieldMarkerPrefix;
} }
/** /**
* Return the prefix for parameters that mark potentially empty fields. * Return the prefix for parameters that mark potentially empty fields.
*/ */
@Nullable
public String getFieldMarkerPrefix() { public String getFieldMarkerPrefix() {
return this.fieldMarkerPrefix; return this.fieldMarkerPrefix;
} }
@@ -149,13 +152,14 @@ public class WebDataBinder extends DataBinder {
* marker for the given field. * marker for the given field.
* @see #DEFAULT_FIELD_DEFAULT_PREFIX * @see #DEFAULT_FIELD_DEFAULT_PREFIX
*/ */
public void setFieldDefaultPrefix(String fieldDefaultPrefix) { public void setFieldDefaultPrefix(@Nullable String fieldDefaultPrefix) {
this.fieldDefaultPrefix = fieldDefaultPrefix; this.fieldDefaultPrefix = fieldDefaultPrefix;
} }
/** /**
* Return the prefix for parameters that mark default fields. * Return the prefix for parameters that mark default fields.
*/ */
@Nullable
public String getFieldDefaultPrefix() { public String getFieldDefaultPrefix() {
return this.fieldDefaultPrefix; return this.fieldDefaultPrefix;
} }

View File

@@ -117,7 +117,7 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
@Override @Override
public void setServletConfig(@Nullable ServletConfig servletConfig) { public void setServletConfig(@Nullable ServletConfig servletConfig) {
this.servletConfig = servletConfig; this.servletConfig = servletConfig;
if (this.servletContext == null) { if (servletConfig != null && this.servletContext == null) {
setServletContext(servletConfig.getServletContext()); setServletContext(servletConfig.getServletContext());
} }
} }
@@ -131,7 +131,9 @@ public abstract class AbstractRefreshableWebApplicationContext extends AbstractR
@Override @Override
public void setNamespace(@Nullable String namespace) { public void setNamespace(@Nullable String namespace) {
this.namespace = namespace; this.namespace = namespace;
setDisplayName(namespace != null ? "WebApplicationContext for namespace '" + namespace + "'" : null); if (namespace != null) {
setDisplayName("WebApplicationContext for namespace '" + namespace + "'");
}
} }
@Override @Override

View File

@@ -93,7 +93,7 @@ public class StaticWebApplicationContext extends StaticApplicationContext
@Override @Override
public void setServletConfig(@Nullable ServletConfig servletConfig) { public void setServletConfig(@Nullable ServletConfig servletConfig) {
this.servletConfig = servletConfig; this.servletConfig = servletConfig;
if (this.servletContext == null) { if (servletConfig != null && this.servletContext == null) {
this.servletContext = servletConfig.getServletContext(); this.servletContext = servletConfig.getServletContext();
} }
} }
@@ -107,7 +107,9 @@ public class StaticWebApplicationContext extends StaticApplicationContext
@Override @Override
public void setNamespace(@Nullable String namespace) { public void setNamespace(@Nullable String namespace) {
this.namespace = namespace; this.namespace = namespace;
setDisplayName(namespace != null ? "WebApplicationContext for namespace '" + namespace + "'" : null); if (namespace != null) {
setDisplayName("WebApplicationContext for namespace '" + namespace + "'");
}
} }
@Override @Override

View File

@@ -62,6 +62,7 @@ public class RedirectView extends AbstractUrlBasedView {
private boolean propagateQuery = false; private boolean propagateQuery = false;
@Nullable
private String[] hosts; private String[] hosts;
@@ -111,17 +112,14 @@ public class RedirectView extends AbstractUrlBasedView {
* {@link HttpStatus#TEMPORARY_REDIRECT} or * {@link HttpStatus#TEMPORARY_REDIRECT} or
* {@link HttpStatus#PERMANENT_REDIRECT}. * {@link HttpStatus#PERMANENT_REDIRECT}.
*/ */
public void setStatusCode(@Nullable HttpStatus statusCode) { public void setStatusCode(HttpStatus statusCode) {
if (statusCode != null) { Assert.isTrue(statusCode.is3xxRedirection(), "Must be a redirection (3xx status code)");
Assert.isTrue(statusCode.is3xxRedirection(), "Must be a redirection (3xx status code)");
}
this.statusCode = statusCode; this.statusCode = statusCode;
} }
/** /**
* Get the redirect status code to use. * Get the redirect status code to use.
*/ */
@Nullable
public HttpStatus getStatusCode() { public HttpStatus getStatusCode() {
return this.statusCode; return this.statusCode;
} }
@@ -150,13 +148,14 @@ public class RedirectView extends AbstractUrlBasedView {
* <p>If not set (the default) all redirect URLs are encoded. * <p>If not set (the default) all redirect URLs are encoded.
* @param hosts one or more application hosts * @param hosts one or more application hosts
*/ */
public void setHosts(String... hosts) { public void setHosts(@Nullable String... hosts) {
this.hosts = hosts; this.hosts = hosts;
} }
/** /**
* Return the configured application hosts. * Return the configured application hosts.
*/ */
@Nullable
public String[] getHosts() { public String[] getHosts() {
return this.hosts; return this.hosts;
} }
@@ -165,9 +164,6 @@ public class RedirectView extends AbstractUrlBasedView {
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet(); 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. * Convert model to request parameters and redirect to the given URL.
*/ */
@Override @Override
protected Mono<Void> renderInternal(Map<String, Object> model, MediaType contentType, protected Mono<Void> renderInternal(
ServerWebExchange exchange) { Map<String, Object> model, @Nullable MediaType contentType, ServerWebExchange exchange) {
String targetUrl = createTargetUrl(model, exchange); String targetUrl = createTargetUrl(model, exchange);
return sendRedirect(targetUrl, exchange); return sendRedirect(targetUrl, exchange);
@@ -296,10 +292,7 @@ public class RedirectView extends AbstractUrlBasedView {
ServerHttpResponse response = exchange.getResponse(); ServerHttpResponse response = exchange.getResponse();
String encodedURL = (isRemoteHost(targetUrl) ? targetUrl : response.encodeUrl(targetUrl)); String encodedURL = (isRemoteHost(targetUrl) ? targetUrl : response.encodeUrl(targetUrl));
response.getHeaders().setLocation(URI.create(encodedURL)); response.getHeaders().setLocation(URI.create(encodedURL));
HttpStatus status = getStatusCode(); response.setStatusCode(getStatusCode());
if (status != null) {
response.setStatusCode(status);
}
return Mono.empty(); return Mono.empty();
} }

View File

@@ -105,8 +105,6 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
* Specify whether this resolver's cookies should be compliant with BCP 47 * Specify whether this resolver's cookies should be compliant with BCP 47
* language tags instead of Java's legacy locale specification format. * language tags instead of Java's legacy locale specification format.
* The default is {@code false}. * The default is {@code false}.
* <p>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 * @since 4.3
* @see Locale#forLanguageTag(String) * @see Locale#forLanguageTag(String)
* @see Locale#toLanguageTag() * @see Locale#toLanguageTag()
@@ -182,43 +180,48 @@ public class CookieLocaleResolver extends CookieGenerator implements LocaleConte
private void parseLocaleCookieIfNecessary(HttpServletRequest request) { private void parseLocaleCookieIfNecessary(HttpServletRequest request) {
if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) { if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) {
// Retrieve and parse cookie value.
Cookie cookie = WebUtils.getCookie(request, getCookieName());
Locale locale = null; Locale locale = null;
TimeZone timeZone = null; TimeZone timeZone = null;
if (cookie != null) {
String value = cookie.getValue(); // Retrieve and parse cookie value.
String localePart = value; String cookieName = getCookieName();
String timeZonePart = null; if (cookieName != null) {
int spaceIndex = localePart.indexOf(' '); Cookie cookie = WebUtils.getCookie(request, cookieName);
if (spaceIndex != -1) { if (cookie != null) {
localePart = value.substring(0, spaceIndex); String value = cookie.getValue();
timeZonePart = value.substring(spaceIndex + 1); String localePart = value;
} String timeZonePart = null;
try { int spaceIndex = localePart.indexOf(' ');
locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null); if (spaceIndex != -1) {
if (timeZonePart != null) { localePart = value.substring(0, spaceIndex);
timeZone = StringUtils.parseTimeZoneString(timeZonePart); timeZonePart = value.substring(spaceIndex + 1);
} }
} try {
catch (IllegalArgumentException ex) { locale = (!"-".equals(localePart) ? parseLocaleValue(localePart) : null);
if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) { if (timeZonePart != null) {
// Error dispatch: ignore locale/timezone parse exceptions timeZone = StringUtils.parseTimeZoneString(timeZonePart);
if (logger.isDebugEnabled()) {
logger.debug("Ignoring invalid locale cookie '" + getCookieName() +
"' with value [" + value + "] due to error dispatch: " + ex.getMessage());
} }
} }
else { catch (IllegalArgumentException ex) {
throw new IllegalStateException("Invalid locale cookie '" + getCookieName() + if (request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) != null) {
"' with value [" + value + "]: " + ex.getMessage()); // 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, request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
(locale != null ? locale : determineDefaultLocale(request))); (locale != null ? locale : determineDefaultLocale(request)));
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME, request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,

View File

@@ -88,11 +88,14 @@ public class CookieThemeResolver extends CookieGenerator implements ThemeResolve
} }
// Retrieve cookie value from request. // Retrieve cookie value from request.
Cookie cookie = WebUtils.getCookie(request, getCookieName()); String cookieName = getCookieName();
if (cookie != null) { if (cookieName != null) {
String value = cookie.getValue(); Cookie cookie = WebUtils.getCookie(request, cookieName);
if (StringUtils.hasText(value)) { if (cookie != null) {
themeName = value; String value = cookie.getValue();
if (StringUtils.hasText(value)) {
themeName = value;
}
} }
} }