Skip to content

Commit

Permalink
Propagation removed from config.
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Henrique Alves Lima committed Aug 12, 2011
1 parent 47e438a commit 1911531
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 116 deletions.
@@ -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
}
}
}
Expand Up @@ -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}")

Expand Down
@@ -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
}
}
Expand Up @@ -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]

Expand Down
Expand Up @@ -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)
}
}

0 comments on commit 1911531

Please sign in to comment.