Synthesize annotation from map w/ minimal attributes

The initial support for synthesizing an annotation from a Map (or
AnnotationAttributes) introduced in SPR-13067 required that the map
contain key-value pairs for every attribute defined by the supplied
annotationType. However, there are use cases that would benefit from
being able to supply a reduced set of attributes and still have the
annotation synthesized properly.

This commit refines the validation mechanism in
MapAnnotationAttributeExtractor so that a reduced set of attributes may
be supplied. Specifically, if an attribute is missing in the supplied
map the attribute will be set either to value of its alias (if an alias
value configured via @AliasFor exists) or to the value of the
attribute's default value (if defined), and otherwise an exception will
be thrown.

Furthermore, TransactionalTestExecutionListener has been refactored to
take advantage of this new feature by synthesizing an instance of
@TransactionConfiguration solely from the default values of its
declared attributes.

Issue: SPR-13087
This commit is contained in:
Sam Brannen
2015-06-19 14:27:23 +01:00
parent 1e39a18819
commit ece12f9d37
4 changed files with 112 additions and 40 deletions

View File

@@ -30,6 +30,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
@@ -133,11 +134,8 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
private static final Log logger = LogFactory.getLog(TransactionalTestExecutionListener.class);
private static final String DEFAULT_TRANSACTION_MANAGER_NAME = (String) getDefaultValue(
TransactionConfiguration.class, "transactionManager");
private static final Boolean DEFAULT_DEFAULT_ROLLBACK = (Boolean) getDefaultValue(TransactionConfiguration.class,
"defaultRollback");
private static final TransactionConfiguration defaultTransactionConfiguration =
AnnotationUtils.synthesizeAnnotation(Collections.<String, Object> emptyMap(), TransactionConfiguration.class, null);
protected final TransactionAttributeSource attributeSource = new AnnotationTransactionAttributeSource();
@@ -506,21 +504,14 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
txConfig, clazz));
}
String transactionManagerName;
boolean defaultRollback;
if (txConfig != null) {
transactionManagerName = txConfig.transactionManager();
defaultRollback = txConfig.defaultRollback();
}
else {
transactionManagerName = DEFAULT_TRANSACTION_MANAGER_NAME;
defaultRollback = DEFAULT_DEFAULT_ROLLBACK;
if (txConfig == null) {
txConfig = defaultTransactionConfiguration;
}
TransactionConfigurationAttributes configAttributes = new TransactionConfigurationAttributes(
transactionManagerName, defaultRollback);
txConfig.transactionManager(), txConfig.defaultRollback());
if (logger.isDebugEnabled()) {
logger.debug(String.format("Retrieved TransactionConfigurationAttributes %s for class [%s].",
logger.debug(String.format("Using TransactionConfigurationAttributes %s for class [%s].",
configAttributes, clazz));
}
this.configurationAttributes = configAttributes;