Skip to content

Commit 4303fdf

Browse files
committed
DATACMNS-318 - Refined persistence exception translation infrastructure.
Extracted the activation of persistence exception translation into a separate RepositoryProxyPostProcessor. Adapted TransactionalRepositoryFactoryBeanSupport to also register the newly introduced PersistenceExceptionTranslationRepositoryProxyPostProcessor.
1 parent 8a67259 commit 4303fdf

File tree

5 files changed

+148
-38
lines changed

5 files changed

+148
-38
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.repository.core.support;
17+
18+
import org.springframework.aop.framework.ProxyFactory;
19+
import org.springframework.beans.factory.ListableBeanFactory;
20+
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
21+
import org.springframework.util.Assert;
22+
23+
/**
24+
* {@link RepositoryProxyPostProcessor} to register a {@link PersistenceExceptionTranslationInterceptor} on the
25+
* repository proxy.
26+
*
27+
* @author Oliver Gierke
28+
*/
29+
public class PersistenceExceptionTranslationRepositoryProxyPostProcessor implements RepositoryProxyPostProcessor {
30+
31+
private final PersistenceExceptionTranslationInterceptor interceptor;
32+
33+
/**
34+
* Creates a new {@link PersistenceExceptionTranslationRepositoryProxyPostProcessor} using the given
35+
* {@link ListableBeanFactory}.
36+
*
37+
* @param beanFactory must not be {@literal null}.
38+
*/
39+
public PersistenceExceptionTranslationRepositoryProxyPostProcessor(ListableBeanFactory beanFactory) {
40+
41+
Assert.notNull(beanFactory, "BeanFactory must not be null!");
42+
43+
this.interceptor = new PersistenceExceptionTranslationInterceptor();
44+
this.interceptor.setBeanFactory(beanFactory);
45+
this.interceptor.afterPropertiesSet();
46+
}
47+
48+
/*
49+
* (non-Javadoc)
50+
* @see org.springframework.data.repository.core.support.RepositoryProxyPostProcessor#postProcess(org.springframework.aop.framework.ProxyFactory)
51+
*/
52+
public void postProcess(ProxyFactory factory) {
53+
factory.addAdvice(interceptor);
54+
}
55+
}

src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryFactoryBeanSupport.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2010 the original author or authors.
2+
* Copyright 2008-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Reposi
3737

3838
private String transactionManagerName = TxUtils.DEFAULT_TRANSACTION_MANAGER;
3939
private RepositoryProxyPostProcessor txPostProcessor;
40+
private RepositoryProxyPostProcessor exceptionPostProcessor;
4041

4142
/**
4243
* Setter to configure which transaction manager to be used. We have to use the bean name explicitly as otherwise the
@@ -46,7 +47,6 @@ public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Reposi
4647
* @param transactionManager
4748
*/
4849
public void setTransactionManager(String transactionManager) {
49-
5050
this.transactionManagerName = transactionManager == null ? TxUtils.DEFAULT_TRANSACTION_MANAGER : transactionManager;
5151
}
5252

@@ -60,6 +60,7 @@ public void setTransactionManager(String transactionManager) {
6060
protected final RepositoryFactorySupport createRepositoryFactory() {
6161

6262
RepositoryFactorySupport factory = doCreateRepositoryFactory();
63+
factory.addRepositoryProxyPostProcessor(exceptionPostProcessor);
6364
factory.addRepositoryProxyPostProcessor(txPostProcessor);
6465
return factory;
6566
}
@@ -72,17 +73,15 @@ protected final RepositoryFactorySupport createRepositoryFactory() {
7273
protected abstract RepositoryFactorySupport doCreateRepositoryFactory();
7374

7475
/*
75-
* (non-Javadoc)
76-
*
77-
* @see
78-
* org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org
79-
* .springframework.beans.factory.BeanFactory)
80-
*/
76+
* (non-Javadoc)
77+
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
78+
*/
8179
public void setBeanFactory(BeanFactory beanFactory) {
8280

8381
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory);
8482

85-
this.txPostProcessor = new TransactionalRepositoryProxyPostProcessor((ListableBeanFactory) beanFactory,
86-
transactionManagerName);
83+
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
84+
this.txPostProcessor = new TransactionalRepositoryProxyPostProcessor(listableBeanFactory, transactionManagerName);
85+
this.exceptionPostProcessor = new PersistenceExceptionTranslationRepositoryProxyPostProcessor(listableBeanFactory);
8786
}
8887
}

src/main/java/org/springframework/data/repository/core/support/TransactionalRepositoryProxyPostProcessor.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2010 the original author or authors.
2+
* Copyright 2008-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -53,36 +53,30 @@
5353
class TransactionalRepositoryProxyPostProcessor implements RepositoryProxyPostProcessor {
5454

5555
private final TransactionInterceptor transactionInterceptor;
56-
private final PersistenceExceptionTranslationInterceptor petInterceptor;
5756

5857
/**
59-
* Creates a new {@link TransactionalRepositoryProxyPostProcessor}.
58+
* Creates a new {@link TransactionalRepositoryProxyPostProcessor} using the given {@link ListableBeanFactory} and
59+
* transaction manager bean name.
60+
*
61+
* @param beanFactory must not be {@literal null}.
62+
* @param transactionManagerName must not be {@literal null} or empty.
6063
*/
6164
public TransactionalRepositoryProxyPostProcessor(ListableBeanFactory beanFactory, String transactionManagerName) {
6265

6366
Assert.notNull(beanFactory);
6467
Assert.notNull(transactionManagerName);
6568

66-
this.petInterceptor = new PersistenceExceptionTranslationInterceptor();
67-
this.petInterceptor.setBeanFactory(beanFactory);
68-
this.petInterceptor.afterPropertiesSet();
69-
7069
this.transactionInterceptor = new TransactionInterceptor(null, new CustomAnnotationTransactionAttributeSource());
7170
this.transactionInterceptor.setTransactionManagerBeanName(transactionManagerName);
7271
this.transactionInterceptor.setBeanFactory(beanFactory);
7372
this.transactionInterceptor.afterPropertiesSet();
7473
}
7574

7675
/*
77-
* (non-Javadoc)
78-
*
79-
* @see
80-
* org.springframework.data.repository.support.RepositoryProxyPostProcessor
81-
* #postProcess(org.springframework.aop.framework.ProxyFactory)
82-
*/
76+
* (non-Javadoc)
77+
* @see org.springframework.data.repository.core.support.RepositoryProxyPostProcessor#postProcess(org.springframework.aop.framework.ProxyFactory)
78+
*/
8379
public void postProcess(ProxyFactory factory) {
84-
85-
factory.addAdvice(petInterceptor);
8680
factory.addAdvice(transactionInterceptor);
8781
}
8882

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.springframework.data.repository.core.support;
17+
18+
import static org.mockito.Matchers.*;
19+
import static org.mockito.Mockito.*;
20+
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
24+
import org.junit.Before;
25+
import org.junit.Test;
26+
import org.junit.runner.RunWith;
27+
import org.mockito.Mock;
28+
import org.mockito.runners.MockitoJUnitRunner;
29+
import org.springframework.aop.framework.ProxyFactory;
30+
import org.springframework.beans.factory.ListableBeanFactory;
31+
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
32+
import org.springframework.dao.support.PersistenceExceptionTranslator;
33+
34+
/**
35+
* Unit test for {@link TransactionalRepositoryProxyPostProcessor}.
36+
*
37+
* @author Oliver Gierke
38+
* @since 1.6
39+
*/
40+
@RunWith(MockitoJUnitRunner.class)
41+
public class PersistenceExceptionTranslationRepositoryProxyPostProcessorUnitTests {
42+
43+
@Mock
44+
ListableBeanFactory beanFactory;
45+
@Mock
46+
ProxyFactory proxyFactory;
47+
48+
@Before
49+
public void setUp() {
50+
51+
Map<String, PersistenceExceptionTranslator> beans = new HashMap<String, PersistenceExceptionTranslator>();
52+
beans.put("foo", mock(PersistenceExceptionTranslator.class));
53+
when(beanFactory.getBeansOfType(eq(PersistenceExceptionTranslator.class), anyBoolean(), anyBoolean())).thenReturn(
54+
beans);
55+
}
56+
57+
@Test(expected = IllegalArgumentException.class)
58+
public void rejectsNullBeanFactory() throws Exception {
59+
60+
new PersistenceExceptionTranslationRepositoryProxyPostProcessor(null);
61+
}
62+
63+
@Test
64+
public void setsUpBasicInstance() throws Exception {
65+
66+
RepositoryProxyPostProcessor postProcessor = new PersistenceExceptionTranslationRepositoryProxyPostProcessor(
67+
beanFactory);
68+
69+
postProcessor.postProcess(proxyFactory);
70+
71+
verify(proxyFactory).addAdvice(isA(PersistenceExceptionTranslationInterceptor.class));
72+
}
73+
}

src/test/java/org/springframework/data/repository/core/support/TransactionRepositoryProxyPostProcessorUnitTests.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2010 the original author or authors.
2+
* Copyright 2008-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
55
* use this file except in compliance with the License. You may obtain a copy of
@@ -15,9 +15,7 @@
1515
*/
1616
package org.springframework.data.repository.core.support;
1717

18-
import static org.mockito.Matchers.anyBoolean;
19-
import static org.mockito.Matchers.eq;
20-
import static org.mockito.Matchers.isA;
18+
import static org.mockito.Matchers.*;
2119
import static org.mockito.Mockito.*;
2220

2321
import java.util.HashMap;
@@ -30,10 +28,7 @@
3028
import org.mockito.runners.MockitoJUnitRunner;
3129
import org.springframework.aop.framework.ProxyFactory;
3230
import org.springframework.beans.factory.ListableBeanFactory;
33-
import org.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
3431
import org.springframework.dao.support.PersistenceExceptionTranslator;
35-
import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;
36-
import org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor;
3732
import org.springframework.transaction.interceptor.TransactionInterceptor;
3833

3934
/**
@@ -44,8 +39,6 @@
4439
@RunWith(MockitoJUnitRunner.class)
4540
public class TransactionRepositoryProxyPostProcessorUnitTests {
4641

47-
TransactionalRepositoryProxyPostProcessor processor;
48-
4942
@Mock
5043
ListableBeanFactory beanFactory;
5144
@Mock
@@ -62,24 +55,20 @@ public void setUp() {
6255

6356
@Test(expected = IllegalArgumentException.class)
6457
public void rejectsNullBeanFactory() throws Exception {
65-
6658
new TransactionalRepositoryProxyPostProcessor(null, "transactionManager");
6759
}
6860

6961
@Test(expected = IllegalArgumentException.class)
7062
public void rejectsNullTxManagerName() throws Exception {
71-
7263
new TransactionalRepositoryProxyPostProcessor(beanFactory, null);
7364
}
7465

7566
@Test
7667
public void setsUpBasicInstance() throws Exception {
7768

7869
RepositoryProxyPostProcessor postProcessor = new TransactionalRepositoryProxyPostProcessor(beanFactory, "txManager");
79-
8070
postProcessor.postProcess(proxyFactory);
8171

82-
verify(proxyFactory).addAdvice(isA(PersistenceExceptionTranslationInterceptor.class));
8372
verify(proxyFactory).addAdvice(isA(TransactionInterceptor.class));
8473
}
8574
}

0 commit comments

Comments
 (0)