Add bindSynchronizedResource with automatic unbinding after transaction completion

Closes gh-35182
This commit is contained in:
Juergen Hoeller
2025-07-10 17:13:51 +02:00
parent 0a705f467d
commit a3e9f0c16d
2 changed files with 120 additions and 16 deletions
@@ -30,6 +30,7 @@ import org.springframework.transaction.testfixture.CallCountingTransactionManage
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* @author Juergen Hoeller
@@ -54,13 +55,11 @@ class SimpleTransactionScopeTests {
context.refresh();
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
context.getBean(TestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> context.getBean(TestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
context.getBean(DerivedTestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> context.getBean(DerivedTestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
TestBean bean1;
DerivedTestBean bean2;
@@ -99,13 +98,11 @@ class SimpleTransactionScopeTests {
assertThat(bean2b.wasDestroyed()).isTrue();
assertThat(TransactionSynchronizationManager.getResourceMap()).isEmpty();
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
context.getBean(TestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> context.getBean(TestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() ->
context.getBean(DerivedTestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(() -> context.getBean(DerivedTestBean.class))
.withCauseInstanceOf(IllegalStateException.class);
}
@Test
@@ -175,4 +172,46 @@ class SimpleTransactionScopeTests {
}
}
@Test
void bindSynchronizedResource() {
CallCountingTransactionManager tm = new CallCountingTransactionManager();
TransactionTemplate tt = new TransactionTemplate(tm);
tt.execute(status -> {
TestBean tb = new TestBean();
TransactionSynchronizationManager.bindSynchronizedResource("tb", tb);
assertThat(TransactionSynchronizationManager.hasResource("tb")).isTrue();
assertThat(TransactionSynchronizationManager.getResource("tb")).isSameAs(tb);
return null;
});
assertThat(TransactionSynchronizationManager.hasResource("tb")).isFalse();
}
@Test
void bindSynchronizedResourceWithOldValue() {
CallCountingTransactionManager tm = new CallCountingTransactionManager();
TransactionTemplate tt = new TransactionTemplate(tm);
TestBean oldValue = new TestBean();
TransactionSynchronizationManager.bindResource("tb", oldValue);
tt.execute(status -> {
TestBean tb = new TestBean();
TransactionSynchronizationManager.bindSynchronizedResource("tb", tb);
assertThat(TransactionSynchronizationManager.hasResource("tb")).isTrue();
assertThat(TransactionSynchronizationManager.getResource("tb")).isSameAs(tb);
return null;
});
assertThat(TransactionSynchronizationManager.hasResource("tb")).isTrue();
assertThat(TransactionSynchronizationManager.getResource("tb")).isSameAs(oldValue);
TransactionSynchronizationManager.unbindResource("tb");
}
@Test
void bindSynchronizedResourceWithoutTransaction() {
assertThatIllegalStateException().isThrownBy(
() -> TransactionSynchronizationManager.bindSynchronizedResource("tb", new TestBean()));
assertThat(TransactionSynchronizationManager.hasResource("tb")).isFalse();
}
}