Skip to content

Commit 0452d76

Browse files
bighenryjrenaat
authored andcommitted
HHH-13915 : Prevent state sharing in basic proxies.
Basic proxies were being created with a shared interceptor. As the interceptor is stateful, this lead to cross-thread data leakage and thus intermittently broken persistence. This mod creates an interceptor per proxy, preventing leaking of state.
1 parent 41b4fe3 commit 0452d76

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ public class BasicProxyFactoryImpl implements BasicProxyFactory {
2424
private static final String PROXY_NAMING_SUFFIX = "HibernateBasicProxy";
2525

2626
private final Class proxyClass;
27-
private final ProxyConfiguration.Interceptor interceptor;
2827
private final Constructor proxyClassConstructor;
2928

3029
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -54,7 +53,7 @@ public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass,
5453
.intercept( byteBuddyState.getProxyDefinitionHelpers().getInterceptorFieldAccessor() )
5554
)
5655
);
57-
this.interceptor = new PassThroughInterceptor( proxyClass.getName() );
56+
5857
try {
5958
proxyClassConstructor = proxyClass.getConstructor();
6059
}
@@ -76,7 +75,9 @@ public Object getProxy() {
7675
if ( proxyConfiguration == null ) {
7776
throw new HibernateException( "Produced proxy does not correctly implement ProxyConfiguration" );
7877
}
79-
proxyConfiguration.$$_hibernate_set_interceptor( this.interceptor );
78+
// Create a dedicated interceptor for the proxy. This is required as the interceptor is stateful.
79+
final ProxyConfiguration.Interceptor interceptor = new PassThroughInterceptor( proxyClass.getName() );
80+
proxyConfiguration.$$_hibernate_set_interceptor( interceptor );
8081
return instance;
8182
}
8283

hibernate-core/src/test/java/org/hibernate/bytecode/internal/bytebuddy/ByteBuddyBasicProxyFactoryTest.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
import org.hibernate.testing.orm.junit.JiraKey;
1414
import org.junit.Test;
1515

16-
@JiraKey(value = "HHH-12786")
1716
public class ByteBuddyBasicProxyFactoryTest {
1817

1918
private static final BasicProxyFactoryImpl BASIC_PROXY_FACTORY = new BasicProxyFactoryImpl( Entity.class, null, new ByteBuddyState() );
2019

2120
@Test
21+
@JiraKey(value = "HHH-12786")
2222
public void testEqualsHashCode() {
2323
Object entityProxy = BASIC_PROXY_FACTORY.getProxy();
2424

@@ -30,13 +30,15 @@ public void testEqualsHashCode() {
3030
}
3131

3232
@Test
33+
@JiraKey(value = "HHH-12786")
3334
public void testToString() {
3435
Object entityProxy = BASIC_PROXY_FACTORY.getProxy();
3536

3637
assertTrue( entityProxy.toString().contains( "HibernateBasicProxy" ) );
3738
}
3839

3940
@Test
41+
@JiraKey(value = "HHH-12786")
4042
public void testGetterSetter() {
4143
Entity entityProxy = (Entity) BASIC_PROXY_FACTORY.getProxy();
4244

@@ -50,12 +52,23 @@ public void testGetterSetter() {
5052
}
5153

5254
@Test
55+
@JiraKey(value = "HHH-12786")
5356
public void testNonGetterSetterMethod() {
5457
Entity entityProxy = (Entity) BASIC_PROXY_FACTORY.getProxy();
5558

5659
assertNull( entityProxy.otherMethod() );
5760
}
5861

62+
@Test
63+
@JiraKey(value = "HHH-13915")
64+
public void testProxiesDoNotShareState() {
65+
Entity entityAProxy = (Entity) BASIC_PROXY_FACTORY.getProxy();
66+
entityAProxy.setString( "John Irving" );
67+
68+
Entity entityBProxy = (Entity) BASIC_PROXY_FACTORY.getProxy();
69+
assertNull( entityBProxy.getString() );
70+
}
71+
5972
public static class Entity {
6073

6174
private String string;

0 commit comments

Comments
 (0)