DATACMNS-715 - Repository factory now adds TransactionProxy interface if available.
We now leniently add the TransactionProxy marker interface to the repository proxy to opt-out of any further transaction handling potentially applied through @EnableTransactionManagement or its XML equivalent. The interface will be introduced in Spring 4.1.7 / 4.2 RC2 so we're reflectively adding it if present. Might be something we can think of making less indirect for Fowler once 4.1.7 has been released.
This commit is contained in:
@@ -59,6 +59,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware {
|
||||
|
||||
private static final boolean IS_JAVA_8 = org.springframework.util.ClassUtils.isPresent("java.util.Optional",
|
||||
RepositoryFactorySupport.class.getClassLoader());
|
||||
private static final Class<?> TRANSACTION_PROXY_TYPE = getTransactionProxyType();
|
||||
|
||||
private final Map<RepositoryInformationCacheKey, RepositoryInformation> repositoryInformationCache = new HashMap<RepositoryInformationCacheKey, RepositoryInformation>();
|
||||
private final List<RepositoryProxyPostProcessor> postProcessors = new ArrayList<RepositoryProxyPostProcessor>();
|
||||
@@ -174,6 +175,10 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware {
|
||||
result.setTarget(target);
|
||||
result.setInterfaces(new Class[] { repositoryInterface, Repository.class });
|
||||
|
||||
if (TRANSACTION_PROXY_TYPE != null) {
|
||||
result.addInterface(TRANSACTION_PROXY_TYPE);
|
||||
}
|
||||
|
||||
for (RepositoryProxyPostProcessor processor : postProcessors) {
|
||||
processor.postProcess(result, information);
|
||||
}
|
||||
@@ -296,6 +301,21 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TransactionProxy type or {@literal null} if not on the classpath.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static Class<?> getTransactionProxyType() {
|
||||
|
||||
try {
|
||||
return org.springframework.util.ClassUtils
|
||||
.forName("org.springframework.transaction.interceptor.TransactionalProxy", null);
|
||||
} catch (ClassNotFoundException o_O) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This {@code MethodInterceptor} intercepts calls to methods of the custom implementation and delegates the to it if
|
||||
* configured. Furthermore it resolves method calls to finders and triggers execution of them. You can rely on having
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -80,9 +81,8 @@ public class RepositoryFactorySupportUnitTests {
|
||||
|
||||
Mockito.reset(factory.strategy);
|
||||
|
||||
when(
|
||||
factory.strategy.resolveQuery(Mockito.any(Method.class), Mockito.any(RepositoryMetadata.class),
|
||||
Mockito.any(NamedQueries.class))).thenReturn(factory.queryOne, factory.queryTwo);
|
||||
when(factory.strategy.resolveQuery(Mockito.any(Method.class), Mockito.any(RepositoryMetadata.class),
|
||||
Mockito.any(NamedQueries.class))).thenReturn(factory.queryOne, factory.queryTwo);
|
||||
|
||||
factory.addQueryCreationListener(listener);
|
||||
factory.addQueryCreationListener(otherListener);
|
||||
@@ -223,6 +223,26 @@ public class RepositoryFactorySupportUnitTests {
|
||||
factory.addRepositoryProxyPostProcessor(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-715, SPR-13109
|
||||
*/
|
||||
@Test
|
||||
public void addsTransactionProxyInterfaceIfAvailable() throws Exception {
|
||||
|
||||
try {
|
||||
|
||||
Class<?> type = ClassUtils.forName("org.springframework.transaction.interceptor.TransactionalProxy", null);
|
||||
|
||||
SimpleRepository repository = factory.getRepository(SimpleRepository.class);
|
||||
assertThat(repository, is(instanceOf(type)));
|
||||
|
||||
} catch (ClassNotFoundException o_O) {
|
||||
Assume.assumeFalse(true);
|
||||
}
|
||||
}
|
||||
|
||||
interface SimpleRepository extends Repository<Object, Serializable> {}
|
||||
|
||||
interface ObjectRepository extends Repository<Object, Serializable>, ObjectRepositoryCustom {
|
||||
|
||||
Object findByClass(Class<?> clazz);
|
||||
|
||||
Reference in New Issue
Block a user