From 1911531e55008d2ed1a6743ebb873758a1c0f4e3 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Alves Lima Date: Thu, 11 Aug 2011 22:35:28 -0300 Subject: [PATCH] Propagation removed from config. --- .../ConfigurableTransactionInterceptor.groovy | 154 ++++++------------ .../handling/GroovyDynamicMethods.groovy | 13 +- .../MyTransactionAttributeSource.groovy | 78 +++++++++ .../handling/TransactionPropertiesUtil.groovy | 10 ++ .../TransactionPropertiesUtilTests.groovy | 22 +++ 5 files changed, 161 insertions(+), 116 deletions(-) create mode 100644 src/groovy/grails/plugin/transaction/handling/MyTransactionAttributeSource.groovy diff --git a/src/groovy/grails/plugin/transaction/handling/ConfigurableTransactionInterceptor.groovy b/src/groovy/grails/plugin/transaction/handling/ConfigurableTransactionInterceptor.groovy index 46c7775..863e527 100644 --- a/src/groovy/grails/plugin/transaction/handling/ConfigurableTransactionInterceptor.groovy +++ b/src/groovy/grails/plugin/transaction/handling/ConfigurableTransactionInterceptor.groovy @@ -1,142 +1,84 @@ -package grails.plugin.transaction.handling +package grails.plugin.transaction.handling; -import grails.spring.BeanBuilder.ConfigurableRuntimeBeanReference; +import groovy.util.Eval; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method -import java.util.Properties +import java.util.Map; +import java.util.Properties; -import org.apache.commons.beanutils.BeanUtils; -import org.apache.commons.logging.Log -import org.apache.commons.logging.LogFactory +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.grails.commons.GrailsApplication; import org.codehaus.groovy.grails.plugins.support.aware.GrailsApplicationAware; -import org.springframework.transaction.interceptor.DefaultTransactionAttribute; -import org.springframework.transaction.interceptor.RollbackRuleAttribute; -import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; -import org.springframework.transaction.interceptor.TransactionAttribute -import org.springframework.transaction.interceptor.TransactionAttributeSource -import org.springframework.transaction.interceptor.TransactionInterceptor -import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.transaction.interceptor.TransactionAttributeSource; +import org.springframework.transaction.interceptor.TransactionInterceptor; import org.springframework.util.Assert; -public class ConfigurableTransactionInterceptor extends TransactionInterceptor implements GrailsApplicationAware { +@SuppressWarnings("serial") +class ConfigurableTransactionInterceptor extends TransactionInterceptor + implements GrailsApplicationAware { - private final Log log = LogFactory.getLog(getClass()) - private Map configuredDefaults = null - private TransactionAttribute defaults + private final Log log = LogFactory.getLog(getClass()); + @SuppressWarnings("rawtypes") + private Map configuredDefaults = null; public ConfigurableTransactionInterceptor() { - log.debug("constructor()") + log.debug("constructor()"); } @Override public void setTransactionAttributeSource( - TransactionAttributeSource transactionAttributeSource) { - log.debug("setTransactionAttributeSource(): transactionAttributeSource ${transactionAttributeSource}") - transactionAttributeSource = new MyTransactionAttributeSource(transactionAttributeSource) - super.setTransactionAttributeSource(transactionAttributeSource) + TransactionAttributeSource transactionAttributeSource) { + log.debug("setTransactionAttributeSource(): transactionAttributeSource ${transactionAttributeSource}"); + transactionAttributeSource = new MyTransactionAttributeSource( + transactionAttributeSource, this.configuredDefaults); + super.setTransactionAttributeSource(transactionAttributeSource); } @Override public void setTransactionAttributeSources( - TransactionAttributeSource[] transactionAttributeSources) { - log.debug("setTransactionAttributeSources(): transactionAttributeSources ${transactionAttributeSources}") - super.setTransactionAttributeSources(transactionAttributeSources) + TransactionAttributeSource[] transactionAttributeSources) { + log.debug("setTransactionAttributeSources(): transactionAttributeSources ${transactionAttributeSources}"); + super.setTransactionAttributeSources(transactionAttributeSources); } @Override public void setTransactionAttributes(Properties transactionAttributes) { - log.debug("setTransactionAttributes(): transactionAttributes ${transactionAttributes}") - super.setTransactionAttributes(transactionAttributes) + log.debug("setTransactionAttributes(): transactionAttributes ${transactionAttributes}"); + super.setTransactionAttributes(transactionAttributes); } - - - @Override - public TransactionAttributeSource getTransactionAttributeSource() { - //log.debug('getTransactionAttributeSource(): Begin') - TransactionAttributeSource source = super.getTransactionAttributeSource(); - Assert.notNull source - Assert.isAssignable MyTransactionAttributeSource, source.getClass() - return source - //log.debug('getTransactionAttributeSource(): End') + public TransactionAttributeSource getTransactionAttributeSource() { + // log.debug('getTransactionAttributeSource(): Begin') + TransactionAttributeSource source = super + .getTransactionAttributeSource(); + Assert.notNull(source); + + Assert.isAssignable(MyTransactionAttributeSource.class, + source.getClass()); + + return source; + // log.debug('getTransactionAttributeSource(): End') } + @SuppressWarnings("rawtypes") @Override - public void setGrailsApplication(GrailsApplication grailsApplication) { - configuredDefaults = null - defaults = null + public void setGrailsApplication(GrailsApplication grailsApplication) { + configuredDefaults = null; if (grailsApplication != null) { - TransactionPropertiesUtil txPropsUtil = new TransactionPropertiesUtil() - Map config = grailsApplication.mergedConfig.asMap(true).grails.plugin.transactionHandling.declarative - if (config && !config.isEmpty()) { - configuredDefaults = txPropsUtil.expand(config) - defaults = new RuleBasedTransactionAttribute() + TransactionPropertiesUtil txPropsUtil = new TransactionPropertiesUtil(); + Map config = (Map) Eval + .x(grailsApplication, + "x.mergedConfig.asMap(true).grails.plugin.transactionHandling.declarative"); + if (config != null && !config.isEmpty()) { + configuredDefaults = txPropsUtil.expand(txPropsUtil + .removePropagationProperties(config)); } } - + if (log.isDebugEnabled()) { - log.debug("setGrailsApplication(): template ${configuredDefaults}") + log.debug("setGrailsApplication(): template ${configuredDefaults}"); } } - - - - - protected class MyTransactionAttributeSource implements TransactionAttributeSource { - - private final Map cache = new IdentityHashMap() - protected final TransactionAttributeSource source - - public MyTransactionAttributeSource(TransactionAttributeSource source) { - this.source = source - Assert.notNull(this.source) - } - - @Override - public TransactionAttribute getTransactionAttribute(Method method, Class clazz) { - TransactionAttribute att = this.source.getTransactionAttribute(method, clazz) - - if (log.isDebugEnabled()) { - log.debug("getTransactionAttribute(): att ${att}; template ${configuredDefaults}") - } - - if (configuredDefaults != null) { - TransactionAttribute newAtt = cache[att] - if (newAtt == null) { - if (att != null) { - Constructor c = att.getClass().getConstructor(att.getClass()) - newAtt = c.newInstance(att) - } else { - newAtt = new DefaultTransactionAttribute() - } - - for (entry in configuredDefaults.entrySet()) { - if (log.isDebugEnabled()) { - log.debug("getTransactionAttribute(): key ${entry.key}") - } - - if (newAtt[entry.key] == defaults[entry.key] && entry.value != defaults[entry.key]) { - if (log.isDebugEnabled()) { - log.debug("getTransactionAttribute(): ${entry.key} = ${entry.value}") - } - newAtt[entry.key] = entry.value - } - } - } - - cache[att] = newAtt - att = newAtt - } - - if (log.isDebugEnabled()) { - log.debug("getTransactionAttribute(): att = ${att}") - } - - return att - } - } } diff --git a/src/groovy/grails/plugin/transaction/handling/GroovyDynamicMethods.groovy b/src/groovy/grails/plugin/transaction/handling/GroovyDynamicMethods.groovy index d1246e6..620c50d 100644 --- a/src/groovy/grails/plugin/transaction/handling/GroovyDynamicMethods.groovy +++ b/src/groovy/grails/plugin/transaction/handling/GroovyDynamicMethods.groovy @@ -30,16 +30,9 @@ class GroovyDynamicMethods { Map withTrxDefaults = [propagation: 'required'] Map withNewTrxDefaults = [propagation: 'requiresNew'] - for (defaults in [withTrxDefaults, withNewTrxDefaults]) { - Map programmaticDefaults = [:] - for (entry in pluginConfig.programmatic.entrySet()) { - if (!defaults.containsKey(entry.key)) { - programmaticDefaults[entry.key] = entry.value - } - } - programmaticDefaults.putAll(defaults) - defaults.clear(); defaults.putAll(programmaticDefaults) - } + withTrxDefaults.putAll(txPropsUtil.removePropagationProperties(pluginConfig.programmatic)) + withNewTrxDefaults.putAll(txPropsUtil.removePropagationProperties(pluginConfig.programmatic)) + log.debug("withTrxDefaults ${withTrxDefaults}") log.debug("withNewTrxDefaults ${withNewTrxDefaults}") diff --git a/src/groovy/grails/plugin/transaction/handling/MyTransactionAttributeSource.groovy b/src/groovy/grails/plugin/transaction/handling/MyTransactionAttributeSource.groovy new file mode 100644 index 0000000..f0fff6a --- /dev/null +++ b/src/groovy/grails/plugin/transaction/handling/MyTransactionAttributeSource.groovy @@ -0,0 +1,78 @@ +package grails.plugin.transaction.handling; + +import java.lang.reflect.Constructor +import java.lang.reflect.Method +import java.util.IdentityHashMap +import java.util.Map + +import org.apache.commons.logging.Log +import org.apache.commons.logging.LogFactory +import org.springframework.transaction.interceptor.DefaultTransactionAttribute +import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute +import org.springframework.transaction.interceptor.TransactionAttribute +import org.springframework.transaction.interceptor.TransactionAttributeSource +import org.springframework.util.Assert + + +public class MyTransactionAttributeSource implements TransactionAttributeSource { + + private final Log log = LogFactory.getLog(getClass()); + private final Map cache = new IdentityHashMap(); + protected final TransactionAttributeSource source; + private final Map configuredDefaults; + private final TransactionAttribute defaults; + + public MyTransactionAttributeSource(TransactionAttributeSource source, Map configuredDefaults) { + this.source = source; + Assert.notNull(this.source); + this.configuredDefaults = configuredDefaults; + if (this.configuredDefaults != null) { + this.defaults = new RuleBasedTransactionAttribute(); + } else { + this.defaults = null; + } + } + + @Override + public TransactionAttribute getTransactionAttribute(Method method, Class clazz) { + TransactionAttribute att = this.source.getTransactionAttribute(method, clazz) + + if (log.isDebugEnabled()) { + log.debug("getTransactionAttribute(): att ${att}; template ${configuredDefaults}") + } + + if (configuredDefaults != null) { + TransactionAttribute newAtt = cache[att] + if (newAtt == null) { + if (att != null) { + Constructor c = att.getClass().getConstructor(att.getClass()) + newAtt = c.newInstance(att) + } else { + newAtt = new DefaultTransactionAttribute() + } + + for (entry in configuredDefaults.entrySet()) { + if (log.isDebugEnabled()) { + log.debug("getTransactionAttribute(): key ${entry.key}") + } + + if (newAtt[entry.key] == defaults[entry.key] && entry.value != defaults[entry.key]) { + if (log.isDebugEnabled()) { + log.debug("getTransactionAttribute(): ${entry.key} = ${entry.value}") + } + newAtt[entry.key] = entry.value + } + } + } + + cache[att] = newAtt + att = newAtt + } + + if (log.isDebugEnabled()) { + log.debug("getTransactionAttribute(): att = ${att}") + } + + return att + } +} \ No newline at end of file diff --git a/src/groovy/grails/plugin/transaction/handling/TransactionPropertiesUtil.groovy b/src/groovy/grails/plugin/transaction/handling/TransactionPropertiesUtil.groovy index db36154..10164dd 100644 --- a/src/groovy/grails/plugin/transaction/handling/TransactionPropertiesUtil.groovy +++ b/src/groovy/grails/plugin/transaction/handling/TransactionPropertiesUtil.groovy @@ -15,6 +15,16 @@ class TransactionPropertiesUtil { private final Log log = LogFactory.getLog(getClass()) + public LinkedHashMap removePropagationProperties(Map properties) { + Map newProperties = new LinkedHashMap() + for (entry in properties.entrySet()) { + if (!entry.key.startsWith('propagation')) { + newProperties[entry.key] = entry.value + } + } + return newProperties + } + public void applyTo(Map properties, Object target) { Map rollbackMapping = [rollbackFor: RollbackRuleAttribute, noRollbackFor: NoRollbackRuleAttribute] diff --git a/test/unit/grails/plugin/transaction/handling/TransactionPropertiesUtilTests.groovy b/test/unit/grails/plugin/transaction/handling/TransactionPropertiesUtilTests.groovy index 4ff2d12..8c5bf82 100644 --- a/test/unit/grails/plugin/transaction/handling/TransactionPropertiesUtilTests.groovy +++ b/test/unit/grails/plugin/transaction/handling/TransactionPropertiesUtilTests.groovy @@ -85,4 +85,26 @@ class TransactionPropertiesUtilTests extends GrailsUnitTestCase { assertEquals(true, txDef.readOnly) assertEquals([new RollbackRuleAttribute(IllegalArgumentException), new NoRollbackRuleAttribute(IllegalStateException)], txDef.rollbackRules) } + + + void testRemovePropagation() { + Map result = null + + result = txPropsUtil.removePropagationProperties([:]) + assertNotNull result + assertTrue result.isEmpty() + + result = txPropsUtil.removePropagationProperties([propagation:'required']) + assertNotNull result + assertTrue result.isEmpty() + + result = txPropsUtil.removePropagationProperties([isolation:'default']) + assertEquals([isolation:'default'], result) + + result = txPropsUtil.removePropagationProperties([isolation:'default', propagationBehavior: TransactionDefinition.PROPAGATION_MANDATORY, timeout:12]) + assertEquals([isolation:'default', timeout: 12], result) + + result = txPropsUtil.removePropagationProperties([isolationLevel: TransactionDefinition.ISOLATION_REPEATABLE_READ, propagationBehaviorName: 'PROPAGATION_MANDATORY', rollbackFor: [], noRollbackFor: []]) + assertEquals([isolationLevel: TransactionDefinition.ISOLATION_REPEATABLE_READ, rollbackFor: [], noRollbackFor: []], result) + } }