Merge branch '3.1.x'
This commit is contained in:
commit
7636913710
|
|
@ -3,10 +3,11 @@ SPRING FRAMEWORK CHANGELOG
|
||||||
http://www.springsource.org
|
http://www.springsource.org
|
||||||
|
|
||||||
|
|
||||||
Changes in version 3.1.1 (2012-01-16)
|
Changes in version 3.1.1 (2012-02-06)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
* official support for Hibernate 4.0 GA
|
* official support for Hibernate 4.0 GA
|
||||||
|
* JBossNativeJdbcExtractor is compatible with JBoss AS 7 as well
|
||||||
* context:property-placeholder's "file-encoding" attribute value is being applied correctly
|
* context:property-placeholder's "file-encoding" attribute value is being applied correctly
|
||||||
* DataBinder correctly handles ParseException from Formatter for String->String case
|
* DataBinder correctly handles ParseException from Formatter for String->String case
|
||||||
* CacheNamespaceHandler actually parses cache:annotation-driven's "key-generator" attribute
|
* CacheNamespaceHandler actually parses cache:annotation-driven's "key-generator" attribute
|
||||||
|
|
@ -14,6 +15,7 @@ Changes in version 3.1.1 (2012-01-16)
|
||||||
* fixed LocalContainerEntityManagerFactoryBean's "packagesToScan" to avoid additional provider scan
|
* fixed LocalContainerEntityManagerFactoryBean's "packagesToScan" to avoid additional provider scan
|
||||||
* added protected "isPersistenceUnitOverrideAllowed()" method to DefaultPersistenceUnitManager
|
* added protected "isPersistenceUnitOverrideAllowed()" method to DefaultPersistenceUnitManager
|
||||||
* Hibernate synchronization properly unbinds Session even in case of afterCompletion exception
|
* Hibernate synchronization properly unbinds Session even in case of afterCompletion exception
|
||||||
|
* Hibernate exception translation covers NonUniqueObjectException to DuplicateKeyException case
|
||||||
* Hibernate 4 LocalSessionFactoryBean implements PersistenceExceptionTranslator interface as well
|
* Hibernate 4 LocalSessionFactoryBean implements PersistenceExceptionTranslator interface as well
|
||||||
* Hibernate 4 LocalSessionFactoryBean does not insist on a "dataSource" reference being set
|
* Hibernate 4 LocalSessionFactoryBean does not insist on a "dataSource" reference being set
|
||||||
* added "entityInterceptor" property to Hibernate 4 LocalSessionFactoryBean
|
* added "entityInterceptor" property to Hibernate 4 LocalSessionFactoryBean
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,15 @@ public class EhCacheCacheManager extends AbstractCacheManager {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the backing EhCache {@link net.sf.ehcache.CacheManager}.
|
* Returns the backing Ehcache {@link net.sf.ehcache.CacheManager}.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public net.sf.ehcache.CacheManager getCacheManager() {
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the backing EhCache {@link net.sf.ehcache.CacheManager}.
|
||||||
*/
|
*/
|
||||||
public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
|
public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
|
||||||
this.cacheManager = cacheManager;
|
this.cacheManager = cacheManager;
|
||||||
|
|
@ -75,5 +83,4 @@ public class EhCacheCacheManager extends AbstractCacheManager {
|
||||||
}
|
}
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -28,7 +28,8 @@ import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the {@link NativeJdbcExtractor} interface for JBoss,
|
* Implementation of the {@link NativeJdbcExtractor} interface for JBoss,
|
||||||
* supporting JBoss Application Server 3.2.4+.
|
* supporting JBoss Application Server 3.2.4+. As of Spring 3.1.1, it also
|
||||||
|
* supports JBoss 7.
|
||||||
*
|
*
|
||||||
* <p>Returns the underlying native Connection, Statement, etc to
|
* <p>Returns the underlying native Connection, Statement, etc to
|
||||||
* application code instead of JBoss' wrapper implementations.
|
* application code instead of JBoss' wrapper implementations.
|
||||||
|
|
@ -47,11 +48,11 @@ import org.springframework.util.ReflectionUtils;
|
||||||
*/
|
*/
|
||||||
public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
|
public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
|
||||||
|
|
||||||
private static final String WRAPPED_CONNECTION_NAME = "org.jboss.resource.adapter.jdbc.WrappedConnection";
|
// JBoss 7
|
||||||
|
private static final String JBOSS_JCA_PREFIX = "org.jboss.jca.adapters.jdbc.";
|
||||||
|
|
||||||
private static final String WRAPPED_STATEMENT_NAME = "org.jboss.resource.adapter.jdbc.WrappedStatement";
|
// JBoss <= 6
|
||||||
|
private static final String JBOSS_RESOURCE_PREFIX = "org.jboss.resource.adapter.jdbc.";
|
||||||
private static final String WRAPPED_RESULT_SET_NAME = "org.jboss.resource.adapter.jdbc.WrappedResultSet";
|
|
||||||
|
|
||||||
|
|
||||||
private Class wrappedConnectionClass;
|
private Class wrappedConnectionClass;
|
||||||
|
|
@ -72,10 +73,26 @@ public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
|
||||||
* so we can get the underlying vendor connection using reflection.
|
* so we can get the underlying vendor connection using reflection.
|
||||||
*/
|
*/
|
||||||
public JBossNativeJdbcExtractor() {
|
public JBossNativeJdbcExtractor() {
|
||||||
|
String prefix = JBOSS_JCA_PREFIX;
|
||||||
try {
|
try {
|
||||||
this.wrappedConnectionClass = getClass().getClassLoader().loadClass(WRAPPED_CONNECTION_NAME);
|
// trying JBoss 7 jca package first...
|
||||||
this.wrappedStatementClass = getClass().getClassLoader().loadClass(WRAPPED_STATEMENT_NAME);
|
this.wrappedConnectionClass = getClass().getClassLoader().loadClass(prefix + "WrappedConnection");
|
||||||
this.wrappedResultSetClass = getClass().getClassLoader().loadClass(WRAPPED_RESULT_SET_NAME);
|
}
|
||||||
|
catch (ClassNotFoundException ex) {
|
||||||
|
// JBoss 7 jca package not found -> try traditional resource package.
|
||||||
|
prefix = JBOSS_RESOURCE_PREFIX;
|
||||||
|
try {
|
||||||
|
this.wrappedConnectionClass = getClass().getClassLoader().loadClass(prefix + "WrappedConnection");
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException ex2) {
|
||||||
|
throw new IllegalStateException("Could not initialize JBossNativeJdbcExtractor: neither JBoss 7's [" +
|
||||||
|
JBOSS_JCA_PREFIX + ".WrappedConnection] nor traditional JBoss [" + JBOSS_RESOURCE_PREFIX +
|
||||||
|
".WrappedConnection] found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.wrappedStatementClass = getClass().getClassLoader().loadClass(prefix + "WrappedStatement");
|
||||||
|
this.wrappedResultSetClass = getClass().getClassLoader().loadClass(prefix + "WrappedResultSet");
|
||||||
this.getUnderlyingConnectionMethod =
|
this.getUnderlyingConnectionMethod =
|
||||||
this.wrappedConnectionClass.getMethod("getUnderlyingConnection", (Class[]) null);
|
this.wrappedConnectionClass.getMethod("getUnderlyingConnection", (Class[]) null);
|
||||||
this.getUnderlyingStatementMethod =
|
this.getUnderlyingStatementMethod =
|
||||||
|
|
@ -85,7 +102,7 @@ public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Could not initialize JBossNativeJdbcExtractor because JBoss API classes are not available: " + ex);
|
"Could not initialize JBossNativeJdbcExtractor because of missing JBoss API methods/classes: " + ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,7 @@
|
||||||
|
|
||||||
<xsd:element name="embedded-database">
|
<xsd:element name="embedded-database">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation
|
<xsd:documentation source="java:org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean"><![CDATA[
|
||||||
source="java:org.springframework.jdbc.embedded.EmbeddedDataSourceFactoryBean"><![CDATA[
|
|
||||||
Creates an embedded database instance and makes it available to other beans as a javax.sql.DataSource.
|
Creates an embedded database instance and makes it available to other beans as a javax.sql.DataSource.
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
<xsd:appinfo>
|
<xsd:appinfo>
|
||||||
|
|
@ -48,7 +47,7 @@
|
||||||
|
|
||||||
<xsd:element name="initialize-database">
|
<xsd:element name="initialize-database">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation source="java:org.springframework.jdbc.embedded.DataSourceInitializer"><![CDATA[
|
<xsd:documentation source="java:org.springframework.jdbc.datasource.init.DataSourceInitializer"><![CDATA[
|
||||||
Initializes a database instance with SQL scripts provided in nested <script/> elements.
|
Initializes a database instance with SQL scripts provided in nested <script/> elements.
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<xsd:element name="embedded-database">
|
<xsd:element name="embedded-database">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation source="java:org.springframework.jdbc.embedded.EmbeddedDataSourceFactoryBean"><![CDATA[
|
<xsd:documentation source="java:org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryBean"><![CDATA[
|
||||||
Creates an embedded database instance and makes it available to other beans as a javax.sql.DataSource.
|
Creates an embedded database instance and makes it available to other beans as a javax.sql.DataSource.
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
<xsd:appinfo>
|
<xsd:appinfo>
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
<xsd:element name="initialize-database">
|
<xsd:element name="initialize-database">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation source="java:org.springframework.jdbc.embedded.DataSourceInitializer"><![CDATA[
|
<xsd:documentation source="java:org.springframework.jdbc.datasource.init.DataSourceInitializer"><![CDATA[
|
||||||
Initializes a database instance with SQL scripts provided in nested <script/> elements.
|
Initializes a database instance with SQL scripts provided in nested <script/> elements.
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -32,6 +32,7 @@ import org.hibernate.FlushMode;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
|
import org.hibernate.NonUniqueObjectException;
|
||||||
import org.hibernate.NonUniqueResultException;
|
import org.hibernate.NonUniqueResultException;
|
||||||
import org.hibernate.ObjectDeletedException;
|
import org.hibernate.ObjectDeletedException;
|
||||||
import org.hibernate.PersistentObjectException;
|
import org.hibernate.PersistentObjectException;
|
||||||
|
|
@ -58,6 +59,7 @@ import org.springframework.dao.CannotAcquireLockException;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||||
|
|
@ -648,6 +650,17 @@ public abstract class SessionFactoryUtils {
|
||||||
if (ex instanceof JDBCException) {
|
if (ex instanceof JDBCException) {
|
||||||
return new HibernateJdbcException((JDBCException) ex);
|
return new HibernateJdbcException((JDBCException) ex);
|
||||||
}
|
}
|
||||||
|
// end of JDBCException (subclass) handling
|
||||||
|
|
||||||
|
if (ex instanceof QueryException) {
|
||||||
|
return new HibernateQueryException((QueryException) ex);
|
||||||
|
}
|
||||||
|
if (ex instanceof NonUniqueResultException) {
|
||||||
|
return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
||||||
|
}
|
||||||
|
if (ex instanceof NonUniqueObjectException) {
|
||||||
|
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
if (ex instanceof PropertyValueException) {
|
if (ex instanceof PropertyValueException) {
|
||||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
@ -660,18 +673,12 @@ public abstract class SessionFactoryUtils {
|
||||||
if (ex instanceof ObjectDeletedException) {
|
if (ex instanceof ObjectDeletedException) {
|
||||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof QueryException) {
|
|
||||||
return new HibernateQueryException((QueryException) ex);
|
|
||||||
}
|
|
||||||
if (ex instanceof UnresolvableObjectException) {
|
if (ex instanceof UnresolvableObjectException) {
|
||||||
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
|
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof WrongClassException) {
|
if (ex instanceof WrongClassException) {
|
||||||
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
|
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof NonUniqueResultException) {
|
|
||||||
return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
|
||||||
}
|
|
||||||
if (ex instanceof StaleObjectStateException) {
|
if (ex instanceof StaleObjectStateException) {
|
||||||
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
|
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
|
import org.hibernate.NonUniqueObjectException;
|
||||||
import org.hibernate.NonUniqueResultException;
|
import org.hibernate.NonUniqueResultException;
|
||||||
import org.hibernate.ObjectDeletedException;
|
import org.hibernate.ObjectDeletedException;
|
||||||
import org.hibernate.PersistentObjectException;
|
import org.hibernate.PersistentObjectException;
|
||||||
|
|
@ -47,6 +48,7 @@ import org.springframework.dao.CannotAcquireLockException;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.DataAccessResourceFailureException;
|
import org.springframework.dao.DataAccessResourceFailureException;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||||
|
|
@ -164,6 +166,17 @@ public abstract class SessionFactoryUtils {
|
||||||
if (ex instanceof JDBCException) {
|
if (ex instanceof JDBCException) {
|
||||||
return new HibernateJdbcException((JDBCException) ex);
|
return new HibernateJdbcException((JDBCException) ex);
|
||||||
}
|
}
|
||||||
|
// end of JDBCException (subclass) handling
|
||||||
|
|
||||||
|
if (ex instanceof QueryException) {
|
||||||
|
return new HibernateQueryException((QueryException) ex);
|
||||||
|
}
|
||||||
|
if (ex instanceof NonUniqueResultException) {
|
||||||
|
return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
||||||
|
}
|
||||||
|
if (ex instanceof NonUniqueObjectException) {
|
||||||
|
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
if (ex instanceof PropertyValueException) {
|
if (ex instanceof PropertyValueException) {
|
||||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
@ -176,18 +189,12 @@ public abstract class SessionFactoryUtils {
|
||||||
if (ex instanceof ObjectDeletedException) {
|
if (ex instanceof ObjectDeletedException) {
|
||||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof QueryException) {
|
|
||||||
return new HibernateQueryException((QueryException) ex);
|
|
||||||
}
|
|
||||||
if (ex instanceof UnresolvableObjectException) {
|
if (ex instanceof UnresolvableObjectException) {
|
||||||
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
|
return new HibernateObjectRetrievalFailureException((UnresolvableObjectException) ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof WrongClassException) {
|
if (ex instanceof WrongClassException) {
|
||||||
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
|
return new HibernateObjectRetrievalFailureException((WrongClassException) ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof NonUniqueResultException) {
|
|
||||||
return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
|
|
||||||
}
|
|
||||||
if (ex instanceof StaleObjectStateException) {
|
if (ex instanceof StaleObjectStateException) {
|
||||||
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
|
return new HibernateOptimisticLockingFailureException((StaleObjectStateException) ex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,8 +173,8 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
|
||||||
* Returns:
|
* Returns:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>0 if the two conditions have the same number of expressions
|
* <li>0 if the two conditions have the same number of expressions
|
||||||
* <li>Less than 1 if "this" has more or more specific media type expressions
|
* <li>Less than 0 if "this" has more or more specific media type expressions
|
||||||
* <li>Greater than 1 if "other" has more or more specific media type expressions
|
* <li>Greater than 0 if "other" has more or more specific media type expressions
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>It is assumed that both instances have been obtained via
|
* <p>It is assumed that both instances have been obtained via
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,8 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
|
||||||
* Returns:
|
* Returns:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>0 if the two conditions have the same number of header expressions
|
* <li>0 if the two conditions have the same number of header expressions
|
||||||
* <li>Less than 1 if "this" instance has more header expressions
|
* <li>Less than 0 if "this" instance has more header expressions
|
||||||
* <li>Greater than 1 if the "other" instance has more header expressions
|
* <li>Greater than 0 if the "other" instance has more header expressions
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>It is assumed that both instances have been obtained via
|
* <p>It is assumed that both instances have been obtained via
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,8 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
|
||||||
* Returns:
|
* Returns:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>0 if the two conditions have the same number of parameter expressions
|
* <li>0 if the two conditions have the same number of parameter expressions
|
||||||
* <li>Less than 1 if "this" instance has more parameter expressions
|
* <li>Less than 0 if "this" instance has more parameter expressions
|
||||||
* <li>Greater than 1 if the "other" instance has more parameter expressions
|
* <li>Greater than 0 if the "other" instance has more parameter expressions
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>It is assumed that both instances have been obtained via
|
* <p>It is assumed that both instances have been obtained via
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,8 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
|
||||||
* Returns:
|
* Returns:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>0 if the two conditions contain the same number of HTTP request methods.
|
* <li>0 if the two conditions contain the same number of HTTP request methods.
|
||||||
* <li>Less than 1 if "this" instance has an HTTP request method but "other" doesn't.
|
* <li>Less than 0 if "this" instance has an HTTP request method but "other" doesn't.
|
||||||
* <li>Greater than 1 "other" has an HTTP request method but "this" doesn't.
|
* <li>Greater than 0 "other" has an HTTP request method but "this" doesn't.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>It is assumed that both instances have been obtained via
|
* <p>It is assumed that both instances have been obtained via
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||||
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
|
||||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
import org.springframework.web.servlet.SmartView;
|
||||||
|
import org.springframework.web.servlet.View;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles return values of type {@link ModelAndView} copying view and model
|
* Handles return values of type {@link ModelAndView} copying view and model
|
||||||
|
|
@ -48,17 +50,29 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
|
||||||
MethodParameter returnType,
|
MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest) throws Exception {
|
NativeWebRequest webRequest) throws Exception {
|
||||||
if (returnValue != null) {
|
if (returnValue == null) {
|
||||||
ModelAndView mav = (ModelAndView) returnValue;
|
mavContainer.setRequestHandled(true);
|
||||||
mavContainer.setViewName(mav.getViewName());
|
return;
|
||||||
if (!mav.isReference()) {
|
}
|
||||||
mavContainer.setView(mav.getView());
|
|
||||||
|
ModelAndView mav = (ModelAndView) returnValue;
|
||||||
|
if (mav.isReference()) {
|
||||||
|
String viewName = mav.getViewName();
|
||||||
|
mavContainer.setViewName(viewName);
|
||||||
|
if (viewName != null && viewName.startsWith("redirect:")) {
|
||||||
|
mavContainer.setRedirectModelScenario(true);
|
||||||
}
|
}
|
||||||
mavContainer.addAllAttributes(mav.getModel());
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mavContainer.setRequestHandled(true);
|
View view = mav.getView();
|
||||||
|
mavContainer.setView(view);
|
||||||
|
if (view instanceof SmartView) {
|
||||||
|
if (((SmartView) view).isRedirectView()) {
|
||||||
|
mavContainer.setRedirectModelScenario(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mavContainer.addAllAttributes(mav.getModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotSame;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
@ -26,10 +28,11 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.web.context.request.ServletWebRequest;
|
import org.springframework.web.context.request.ServletWebRequest;
|
||||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler;
|
import org.springframework.web.servlet.mvc.support.RedirectAttributesModelMap;
|
||||||
import org.springframework.web.servlet.view.RedirectView;
|
import org.springframework.web.servlet.view.RedirectView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -45,44 +48,90 @@ public class ModelAndViewMethodReturnValueHandlerTests {
|
||||||
|
|
||||||
private ServletWebRequest webRequest;
|
private ServletWebRequest webRequest;
|
||||||
|
|
||||||
|
private MethodParameter returnParamModelAndView;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() throws Exception {
|
||||||
this.handler = new ModelAndViewMethodReturnValueHandler();
|
this.handler = new ModelAndViewMethodReturnValueHandler();
|
||||||
this.mavContainer = new ModelAndViewContainer();
|
this.mavContainer = new ModelAndViewContainer();
|
||||||
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
this.webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||||
|
this.returnParamModelAndView = getReturnValueParam("modelAndView");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void supportsReturnType() throws Exception {
|
public void supportsReturnType() throws Exception {
|
||||||
assertTrue(handler.supportsReturnType(getReturnValueParam("modelAndView")));
|
assertTrue(handler.supportsReturnType(returnParamModelAndView));
|
||||||
assertFalse(handler.supportsReturnType(getReturnValueParam("viewName")));
|
assertFalse(handler.supportsReturnType(getReturnValueParam("viewName")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handleReturnValueViewName() throws Exception {
|
public void handleViewReference() throws Exception {
|
||||||
ModelAndView mav = new ModelAndView("viewName", "attrName", "attrValue");
|
ModelAndView mav = new ModelAndView("viewName", "attrName", "attrValue");
|
||||||
handler.handleReturnValue(mav, getReturnValueParam("modelAndView"), mavContainer, webRequest);
|
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
|
||||||
|
|
||||||
assertEquals("viewName", mavContainer.getView());
|
assertEquals("viewName", mavContainer.getView());
|
||||||
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
|
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handleReturnValueView() throws Exception {
|
public void handleViewInstance() throws Exception {
|
||||||
ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue");
|
ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue");
|
||||||
handler.handleReturnValue(mav, getReturnValueParam("modelAndView"), mavContainer, webRequest);
|
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
|
||||||
|
|
||||||
assertEquals(RedirectView.class, mavContainer.getView().getClass());
|
assertEquals(RedirectView.class, mavContainer.getView().getClass());
|
||||||
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
|
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handleReturnValueNull() throws Exception {
|
public void handleNull() throws Exception {
|
||||||
handler.handleReturnValue(null, getReturnValueParam("modelAndView"), mavContainer, webRequest);
|
handler.handleReturnValue(null, returnParamModelAndView, mavContainer, webRequest);
|
||||||
|
|
||||||
assertTrue(mavContainer.isRequestHandled());
|
assertTrue(mavContainer.isRequestHandled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleRedirectAttributesWithViewReference() throws Exception {
|
||||||
|
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
|
||||||
|
mavContainer.setRedirectModel(redirectAttributes);
|
||||||
|
|
||||||
|
ModelAndView mav = new ModelAndView(new RedirectView(), "attrName", "attrValue");
|
||||||
|
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
|
||||||
|
|
||||||
|
assertEquals(RedirectView.class, mavContainer.getView().getClass());
|
||||||
|
assertEquals("attrValue", mavContainer.getModel().get("attrName"));
|
||||||
|
assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes,
|
||||||
|
mavContainer.getModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleRedirectAttributesWithViewInstance() throws Exception {
|
||||||
|
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
|
||||||
|
mavContainer.setRedirectModel(redirectAttributes);
|
||||||
|
|
||||||
|
ModelAndView mav = new ModelAndView("redirect:viewName", "attrName", "attrValue");
|
||||||
|
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
|
||||||
|
|
||||||
|
ModelMap model = mavContainer.getModel();
|
||||||
|
assertEquals("redirect:viewName", mavContainer.getViewName());
|
||||||
|
assertEquals("attrValue", model.get("attrName"));
|
||||||
|
assertSame("RedirectAttributes should be used if controller redirects", redirectAttributes, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleRedirectAttributesWithoutRedirect() throws Exception {
|
||||||
|
RedirectAttributesModelMap redirectAttributes = new RedirectAttributesModelMap();
|
||||||
|
mavContainer.setRedirectModel(redirectAttributes);
|
||||||
|
|
||||||
|
ModelAndView mav = new ModelAndView();
|
||||||
|
handler.handleReturnValue(mav, returnParamModelAndView, mavContainer, webRequest);
|
||||||
|
|
||||||
|
ModelMap model = mavContainer.getModel();
|
||||||
|
assertEquals(null, mavContainer.getView());
|
||||||
|
assertTrue(mavContainer.getModel().isEmpty());
|
||||||
|
assertNotSame("RedirectAttributes should not be used if controller doesn't redirect", redirectAttributes, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private MethodParameter getReturnValueParam(String methodName) throws Exception {
|
private MethodParameter getReturnValueParam(String methodName) throws Exception {
|
||||||
Method method = getClass().getDeclaredMethod(methodName);
|
Method method = getClass().getDeclaredMethod(methodName);
|
||||||
return new MethodParameter(method, -1);
|
return new MethodParameter(method, -1);
|
||||||
|
|
|
||||||
|
|
@ -707,6 +707,10 @@ productList.url=/WEB-INF/jsp/productlist.jsp</programlisting>
|
||||||
<para><literal>path="lastName"</literal> - displays all errors
|
<para><literal>path="lastName"</literal> - displays all errors
|
||||||
associated with the <literal>lastName</literal> field</para>
|
associated with the <literal>lastName</literal> field</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>if <literal>path</literal> is omitted - object errors only are displayed</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
<para>The example below will display a list of errors at the top of
|
<para>The example below will display a list of errors at the top of
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue