From bcc21b1c041436ab61479da386fede5a8cf68cae Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Thu, 1 Sep 2022 22:45:17 +1200 Subject: [PATCH] #2818 - Fix Concurrent modification of listenerNotify TransactionEvent list The issue fixed here is that SavepointTransaction was effectively using the TransactionEvent of the underlying 'parent' transaction. The fix is for SavepointTransaction to have its own TransactionEvent. --- .../server/transaction/SavepointTransaction.java | 10 ++++++++++ .../tests/transaction/TestNestedSubTransaction.java | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/transaction/SavepointTransaction.java b/ebean-core/src/main/java/io/ebeaninternal/server/transaction/SavepointTransaction.java index aa4bc978e..8dfcd3b37 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/transaction/SavepointTransaction.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/transaction/SavepointTransaction.java @@ -2,6 +2,7 @@ package io.ebeaninternal.server.transaction; import io.ebeaninternal.api.SpiTransaction; import io.ebeaninternal.api.SpiTransactionProxy; +import io.ebeaninternal.api.TransactionEvent; import io.ebeaninternal.server.util.Str; import javax.persistence.PersistenceException; @@ -25,6 +26,7 @@ final class SavepointTransaction extends SpiTransactionProxy { private boolean rollbackOnly; private int state; + private TransactionEvent event; SavepointTransaction(SpiTransaction transaction, TransactionManager manager) throws SQLException { this.manager = manager; @@ -40,6 +42,14 @@ final class SavepointTransaction extends SpiTransactionProxy { this.logPrefix = transaction.getLogPrefix() + spPrefix; } + @Override + public TransactionEvent getEvent() { + if (event == null) { + event = new TransactionEvent(); + } + return event; + } + @Override public String getLogPrefix() { return logPrefix; diff --git a/ebean-test/src/test/java/org/tests/transaction/TestNestedSubTransaction.java b/ebean-test/src/test/java/org/tests/transaction/TestNestedSubTransaction.java index e8f32eced..86161b8aa 100644 --- a/ebean-test/src/test/java/org/tests/transaction/TestNestedSubTransaction.java +++ b/ebean-test/src/test/java/org/tests/transaction/TestNestedSubTransaction.java @@ -4,6 +4,8 @@ import io.ebean.*; import io.ebean.xtest.BaseTestCase; import io.ebean.xtest.IgnorePlatform; import io.ebean.annotation.Platform; +import io.ebeaninternal.api.SpiTransaction; +import io.ebeaninternal.api.TransactionEvent; import org.junit.jupiter.api.Test; import org.tests.model.basic.EBasic; @@ -75,10 +77,15 @@ public class TestNestedSubTransaction extends BaseTestCase { server.save(bean); + TransactionEvent event0 = ((SpiTransaction) txn0).getEvent(); + try (Transaction txn1 = server.beginTransaction()) { bean.setName("updateNested"); server.save(bean); + TransactionEvent event1 = ((SpiTransaction) txn1).getEvent(); + assertThat(event1).isNotSameAs(event0); + try (Transaction txn2 = server.beginTransaction()) { bean.setName("barney"); DB.save(bean);