From bddf3e4b2760b9ce174188ccaa853eaa11a805a8 Mon Sep 17 00:00:00 2001 From: Artem Sidorkin Date: Wed, 24 Feb 2021 17:40:49 +0300 Subject: [PATCH 1/2] Replaced TransactionTemplate by EventuateTransactionTemplate in TransactionalNoopDuplicateMessageDetector. See https://github.com/eventuate-tram/eventuate-tram-core-quarkus/issues/7 --- .../TransactionalNoopDuplicateMessageDetector.java | 10 ++++------ ...ansactionalNoopDuplicateMessageDetectorFactory.java | 5 +++-- .../test/SpringCloudSleuthIntegrationTest.java | 8 ++++++++ ...ionalNoopDuplicateMessageDetectorConfiguration.java | 7 +++++-- .../spring/inmemory/InMemoryMessageProducerTest.java | 7 +++++++ .../io/eventuate/tram/testing/MessageTrackerTest.java | 8 ++++++++ 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/eventuate-tram-consumer-jdbc/src/main/java/io/eventuate/tram/consumer/jdbc/TransactionalNoopDuplicateMessageDetector.java b/eventuate-tram-consumer-jdbc/src/main/java/io/eventuate/tram/consumer/jdbc/TransactionalNoopDuplicateMessageDetector.java index ed4f68d2..79727329 100644 --- a/eventuate-tram-consumer-jdbc/src/main/java/io/eventuate/tram/consumer/jdbc/TransactionalNoopDuplicateMessageDetector.java +++ b/eventuate-tram-consumer-jdbc/src/main/java/io/eventuate/tram/consumer/jdbc/TransactionalNoopDuplicateMessageDetector.java @@ -1,18 +1,18 @@ package io.eventuate.tram.consumer.jdbc; +import io.eventuate.common.jdbc.EventuateTransactionTemplate; import io.eventuate.tram.consumer.common.DuplicateMessageDetector; import io.eventuate.tram.consumer.common.SubscriberIdAndMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.transaction.support.TransactionTemplate; public class TransactionalNoopDuplicateMessageDetector implements DuplicateMessageDetector { private Logger logger = LoggerFactory.getLogger(getClass()); - private TransactionTemplate transactionTemplate; + private EventuateTransactionTemplate transactionTemplate; - public TransactionalNoopDuplicateMessageDetector(TransactionTemplate transactionTemplate) { + public TransactionalNoopDuplicateMessageDetector(EventuateTransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } @@ -23,16 +23,14 @@ public boolean isDuplicate(String consumerId, String messageId) { @Override public void doWithMessage(SubscriberIdAndMessage subscriberIdAndMessage, Runnable callback) { - transactionTemplate.execute(ts -> { + transactionTemplate.executeInTransaction(() -> { try { callback.run(); return null; } catch (Throwable e) { logger.error("Got exception - marking for rollback only", e); - ts.setRollbackOnly(); throw e; } }); - } } diff --git a/eventuate-tram-micronaut-consumer-jdbc/src/main/java/io/eventuate/tram/micronaut/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorFactory.java b/eventuate-tram-micronaut-consumer-jdbc/src/main/java/io/eventuate/tram/micronaut/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorFactory.java index a41a92fc..3caf8006 100644 --- a/eventuate-tram-micronaut-consumer-jdbc/src/main/java/io/eventuate/tram/micronaut/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorFactory.java +++ b/eventuate-tram-micronaut-consumer-jdbc/src/main/java/io/eventuate/tram/micronaut/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorFactory.java @@ -1,5 +1,6 @@ package io.eventuate.tram.micronaut.consumer.jdbc; +import io.eventuate.common.jdbc.EventuateTransactionTemplate; import io.eventuate.tram.consumer.common.DuplicateMessageDetector; import io.eventuate.tram.consumer.jdbc.TransactionalNoopDuplicateMessageDetector; import io.micronaut.context.annotation.Factory; @@ -13,7 +14,7 @@ public class TransactionalNoopDuplicateMessageDetectorFactory { @Singleton @Requires(property = "transactional.noop.duplicate.message.detector.factory.enabled") - public DuplicateMessageDetector duplicateMessageDetector(TransactionTemplate transactionTemplate) { - return new TransactionalNoopDuplicateMessageDetector(transactionTemplate); + public DuplicateMessageDetector duplicateMessageDetector(EventuateTransactionTemplate eventuateTransactionTemplate) { + return new TransactionalNoopDuplicateMessageDetector(eventuateTransactionTemplate); } } diff --git a/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java b/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java index fc68eb48..f1c4d8f8 100644 --- a/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java +++ b/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java @@ -1,5 +1,7 @@ package io.eventuate.tram.spring.cloudsleuthintegration.test; +import io.eventuate.common.common.spring.jdbc.EventuateSpringTransactionTemplate; +import io.eventuate.common.jdbc.EventuateTransactionTemplate; import io.eventuate.tram.spring.inmemory.TramInMemoryConfiguration; import io.eventuate.util.test.async.Eventually; import org.junit.Test; @@ -17,6 +19,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.support.TransactionTemplate; import org.springframework.web.client.RestTemplate; import java.util.List; @@ -41,6 +44,11 @@ public RestTemplate restTemplate() { return new RestTemplate(); } + @Bean + public EventuateTransactionTemplate eventuateTransactionTemplate(TransactionTemplate transactionTemplate) { + return new EventuateSpringTransactionTemplate(transactionTemplate); + } + } @Value("${spring.zipkin.baseUrl}") diff --git a/eventuate-tram-spring-consumer-jdbc/src/main/java/io/eventuate/tram/spring/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorConfiguration.java b/eventuate-tram-spring-consumer-jdbc/src/main/java/io/eventuate/tram/spring/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorConfiguration.java index 8bbf03bf..5d9fd42a 100644 --- a/eventuate-tram-spring-consumer-jdbc/src/main/java/io/eventuate/tram/spring/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorConfiguration.java +++ b/eventuate-tram-spring-consumer-jdbc/src/main/java/io/eventuate/tram/spring/consumer/jdbc/TransactionalNoopDuplicateMessageDetectorConfiguration.java @@ -1,16 +1,19 @@ package io.eventuate.tram.spring.consumer.jdbc; +import io.eventuate.common.jdbc.EventuateTransactionTemplate; +import io.eventuate.common.spring.jdbc.EventuateCommonJdbcOperationsConfiguration; import io.eventuate.tram.consumer.common.DuplicateMessageDetector; import io.eventuate.tram.consumer.jdbc.TransactionalNoopDuplicateMessageDetector; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.transaction.support.TransactionTemplate; @Configuration public class TransactionalNoopDuplicateMessageDetectorConfiguration { @Bean - public DuplicateMessageDetector duplicateMessageDetector(TransactionTemplate transactionTemplate) { - return new TransactionalNoopDuplicateMessageDetector(transactionTemplate); + public DuplicateMessageDetector duplicateMessageDetector(EventuateTransactionTemplate eventuateTransactionTemplate) { + return new TransactionalNoopDuplicateMessageDetector(eventuateTransactionTemplate); } } diff --git a/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java b/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java index 2cd5cd34..44251fa1 100644 --- a/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java +++ b/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java @@ -1,5 +1,7 @@ package io.eventuate.tram.spring.inmemory; +import io.eventuate.common.common.spring.jdbc.EventuateSpringTransactionTemplate; +import io.eventuate.common.jdbc.EventuateTransactionTemplate; import io.eventuate.tram.messaging.consumer.MessageConsumer; import io.eventuate.tram.messaging.producer.MessageProducer; import io.eventuate.tram.inmemory.test.AbstractInMemoryMessageProducerTest; @@ -9,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; @@ -23,6 +26,10 @@ public class InMemoryMessageProducerTest extends AbstractInMemoryMessageProducer @EnableAutoConfiguration @Import({TramInMemoryConfiguration.class}) public static class InMemoryMessagingTestConfiguration { + @Bean + public EventuateTransactionTemplate eventuateTransactionTemplate(TransactionTemplate transactionTemplate) { + return new EventuateSpringTransactionTemplate(transactionTemplate); + } } @Autowired diff --git a/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java b/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java index 2cc727b6..be859c67 100644 --- a/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java +++ b/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java @@ -1,5 +1,7 @@ package io.eventuate.tram.testing; +import io.eventuate.common.common.spring.jdbc.EventuateSpringTransactionTemplate; +import io.eventuate.common.jdbc.EventuateTransactionTemplate; import io.eventuate.tram.commands.common.Command; import io.eventuate.tram.commands.producer.CommandProducer; import io.eventuate.tram.spring.commands.producer.TramCommandProducerConfiguration; @@ -17,6 +19,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.support.TransactionTemplate; import java.util.Collections; import java.util.Set; @@ -39,6 +42,11 @@ public static class MessageTrackerTestConfiguration { public MessageTracker messageTracker(MessageConsumer messageConsumer) { return new MessageTracker(channels, messageConsumer); } + + @Bean + public EventuateTransactionTemplate eventuateTransactionTemplate(TransactionTemplate transactionTemplate) { + return new EventuateSpringTransactionTemplate(transactionTemplate); + } } @Autowired From 816144796eba773cef10dd64622cc712a2cf5a66 Mon Sep 17 00:00:00 2001 From: Artem Sidorkin Date: Thu, 25 Feb 2021 20:32:08 +0300 Subject: [PATCH 2/2] Removed redundant transaction template bean definition. Extracted optimistic locking tests to common module, add tests for spring optimistic locking. --- .../build.gradle | 1 + ...entuateMicronautOptimisticLockingTest.java | 44 +++--------------- .../locking/AbstractTestEntityService.java | 45 ------------------ ...cLockingWithAnnotationTransactionTest.java | 10 +++- ...ithTransactionTemplateTransactionTest.java | 8 ++++ .../locking/TestEntityRepositoryImpl.java | 24 ++++++++++ ...estEntityServiceTransactionAnnotation.java | 38 +++++++++------ .../TestEntityServiceTransactionTemplate.java | 25 ++++------ .../src/test/resources/application.yml | 2 +- .../build.gradle | 8 ++++ ...bstractEventuateOptimisticLockingTest.java | 46 +++++++++++++++++++ .../test/AbstractTestEntityService.java | 36 +++++++++++++++ ...tTestEntityServiceTransactionTemplate.java | 28 +++++++++++ .../locking/common/test}/TestEntity.java | 11 ++++- .../common/test/TestEntityRepository.java | 7 +++ .../SpringCloudSleuthIntegrationTest.java | 12 +---- .../inmemory/InMemoryMessageProducerTest.java | 10 +--- .../build.gradle | 5 ++ .../OptimisticLockingDecorator.java | 2 +- ...timisticLockingDecoratorConfiguration.java | 2 + ...tEventuateSpringOptimisticLockingTest.java | 16 +++++++ ...cLockingWithAnnotationTransactionTest.java | 39 ++++++++++++++++ ...ithTransactionTemplateTransactionTest.java | 39 ++++++++++++++++ .../TestEntityRepositoryConfiguration.java | 20 ++++++++ .../TestEntityRepositoryImpl.java | 21 +++++++++ ...estEntityServiceTransactionAnnotation.java | 35 ++++++++++++++ .../TestEntityServiceTransactionTemplate.java | 25 ++++++++++ .../TestEntitySpringRepository.java | 7 +++ .../resources/application-mssql.properties | 4 ++ .../resources/application-postgres.properties | 5 ++ .../src/test/resources/application.properties | 5 ++ .../tram/testing/MessageTrackerTest.java | 14 ++---- settings.gradle | 1 + 33 files changed, 451 insertions(+), 144 deletions(-) delete mode 100644 eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractTestEntityService.java create mode 100644 eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityRepositoryImpl.java create mode 100644 eventuate-tram-optimistic-locking-common-test/build.gradle create mode 100644 eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractEventuateOptimisticLockingTest.java create mode 100644 eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityService.java create mode 100644 eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityServiceTransactionTemplate.java rename {eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking => eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test}/TestEntity.java (54%) create mode 100644 eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntityRepository.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/AbstractEventuateSpringOptimisticLockingTest.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithAnnotationTransactionTest.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithTransactionTemplateTransactionTest.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryConfiguration.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryImpl.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionAnnotation.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionTemplate.java create mode 100755 eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntitySpringRepository.java create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/resources/application-mssql.properties create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/resources/application-postgres.properties create mode 100644 eventuate-tram-spring-optimistic-locking/src/test/resources/application.properties diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/build.gradle b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/build.gradle index 000bced9..97c5e1a0 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/build.gradle +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/build.gradle @@ -14,6 +14,7 @@ apply plugin: PublicModulePlugin dependencies { compile project(":eventuate-tram-consumer-common") + compile project(":eventuate-tram-optimistic-locking-common-test") compile "io.eventuate.common:eventuate-common-micronaut-spring-jdbc:$eventuateCommonVersion" compile "io.micronaut.configuration:micronaut-hibernate-jpa" diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractEventuateMicronautOptimisticLockingTest.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractEventuateMicronautOptimisticLockingTest.java index c364bf38..83558c2b 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractEventuateMicronautOptimisticLockingTest.java +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractEventuateMicronautOptimisticLockingTest.java @@ -1,49 +1,17 @@ package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; +import io.eventuate.tram.consumer.common.MessageHandlerDecorator; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractEventuateOptimisticLockingTest; import javax.inject.Inject; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicInteger; -abstract public class AbstractEventuateMicronautOptimisticLockingTest { - - private static final int UPDATE_THREADS = 3; +abstract public class AbstractEventuateMicronautOptimisticLockingTest extends AbstractEventuateOptimisticLockingTest { @Inject private OptimisticLockingDecorator optimisticLockingDecorator; - private AtomicInteger attempts = new AtomicInteger(0); - - private CountDownLatch countDownLatch = new CountDownLatch(UPDATE_THREADS); - - protected abstract AbstractTestEntityService testEntityService(); - - @Test - public void shouldRetryOnLockException() throws InterruptedException { - - long testEntityId = testEntityService().createTestEntityInTransaction(); - - for (int i = 0; i < UPDATE_THREADS; i++) updateEntity(testEntityId); - - countDownLatch.await(); - - Assertions.assertTrue(attempts.get() > UPDATE_THREADS); - Assertions.assertEquals(UPDATE_THREADS, testEntityService().getDataInTransaction(testEntityId)); - } - - private void updateEntity(Long testEntityId) { - new Thread(() -> { - - optimisticLockingDecorator.accept(null, subscriberIdAndMessage -> { - attempts.incrementAndGet(); - - testEntityService().incDataInTransaction(testEntityId); - }); - - countDownLatch.countDown(); - - }).start(); + @Override + public MessageHandlerDecorator getOptimisticLockingDecorator() { + return optimisticLockingDecorator; } } \ No newline at end of file diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractTestEntityService.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractTestEntityService.java deleted file mode 100644 index 14b64008..00000000 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/AbstractTestEntityService.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; - -import io.micronaut.spring.tx.annotation.Transactional; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; - -public abstract class AbstractTestEntityService { - - @PersistenceContext - private EntityManager entityManager; - - public abstract Long createTestEntityInTransaction(); - public abstract void incDataInTransaction(Long entityId); - public abstract long getDataInTransaction(Long entityId); - - @Transactional - public Long createTestEntity() { - TestEntity testEntity = new TestEntity(); - entityManager.persist(testEntity); - return testEntity.getId(); - } - - @Transactional - public void incData(Long entityId) { - TestEntity testEntity = entityManager.find(TestEntity.class, entityId); - testEntity.setData(testEntity.getData() + 1); - sleep(); - entityManager.persist(testEntity); - } - - @Transactional - public long getData(Long entityId) { - TestEntity testEntity = entityManager.find(TestEntity.class, entityId); - return testEntity.getData(); - } - - private void sleep() { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } -} diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithAnnotationTransactionTest.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithAnnotationTransactionTest.java index bab07700..fa14daa9 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithAnnotationTransactionTest.java +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithAnnotationTransactionTest.java @@ -1,19 +1,25 @@ package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityService; import io.micronaut.test.annotation.MicronautTest; +import org.junit.jupiter.api.Test; import javax.inject.Inject; @MicronautTest(transactional = false) public class EventuateMicronautOptimisticLockingWithAnnotationTransactionTest extends AbstractEventuateMicronautOptimisticLockingTest { - @Inject private TestEntityServiceTransactionAnnotation testEntityService; - @Override protected AbstractTestEntityService testEntityService() { return testEntityService; } + + @Override + @Test + public void shouldRetryOnLockException() throws InterruptedException { + super.shouldRetryOnLockException(); + } } \ No newline at end of file diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithTransactionTemplateTransactionTest.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithTransactionTemplateTransactionTest.java index ac0530e2..47d22218 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithTransactionTemplateTransactionTest.java +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/EventuateMicronautOptimisticLockingWithTransactionTemplateTransactionTest.java @@ -1,6 +1,8 @@ package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityService; import io.micronaut.test.annotation.MicronautTest; +import org.junit.jupiter.api.Test; import javax.inject.Inject; @@ -14,4 +16,10 @@ public class EventuateMicronautOptimisticLockingWithTransactionTemplateTransacti protected AbstractTestEntityService testEntityService() { return testEntityService; } + + @Override + @Test + public void shouldRetryOnLockException() throws InterruptedException { + super.shouldRetryOnLockException(); + } } \ No newline at end of file diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityRepositoryImpl.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityRepositoryImpl.java new file mode 100644 index 00000000..eccb630f --- /dev/null +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityRepositoryImpl.java @@ -0,0 +1,24 @@ +package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; + +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntity; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; + +import javax.inject.Singleton; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +@Singleton +public class TestEntityRepositoryImpl implements TestEntityRepository { + @PersistenceContext + private EntityManager entityManager; + + @Override + public TestEntity find(Long entityId) { + return entityManager.find(TestEntity.class, entityId); + } + + @Override + public void persist(TestEntity testEntity) { + entityManager.persist(testEntity); + } +} diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionAnnotation.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionAnnotation.java index 59df257c..544aeb36 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionAnnotation.java +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionAnnotation.java @@ -1,28 +1,40 @@ package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityService; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; import io.micronaut.spring.tx.annotation.Transactional; +import javax.inject.Inject; import javax.inject.Singleton; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; @Singleton public class TestEntityServiceTransactionAnnotation extends AbstractTestEntityService { + @Inject + private TestEntityRepository testEntityRepository; - @Transactional - @Override - public Long createTestEntityInTransaction() { - return createTestEntity(); - } + @Transactional + @Override + public Long createTestEntityInTransaction() { + return createTestEntity(); + } - @Transactional - @Override - public void incDataInTransaction(Long entityId) { - incData(entityId); - } + @Transactional + @Override + public void incDataInTransaction(Long entityId) { + incData(entityId); + } - @Transactional - @Override - public long getDataInTransaction(Long entityId) { + @Transactional + @Override + public long getDataInTransaction(Long entityId) { return getData(entityId); } + + @Override + public TestEntityRepository getTestEntityRepository() { + return testEntityRepository; + } } diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionTemplate.java b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionTemplate.java index 79f9adec..28fe3f72 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionTemplate.java +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntityServiceTransactionTemplate.java @@ -1,33 +1,28 @@ package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; import io.eventuate.common.jdbc.EventuateTransactionTemplate; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityServiceTransactionTemplate; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; import javax.inject.Inject; import javax.inject.Singleton; @Singleton -public class TestEntityServiceTransactionTemplate extends AbstractTestEntityService { +public class TestEntityServiceTransactionTemplate extends AbstractTestEntityServiceTransactionTemplate { @Inject - private EventuateTransactionTemplate eventuateTransactionalTemplate; + private TestEntityRepository testEntityRepository; - @Override - public Long createTestEntityInTransaction() { - return eventuateTransactionalTemplate.executeInTransaction(this::createTestEntity); - } + @Inject + private EventuateTransactionTemplate eventuateTransactionalTemplate; @Override - public void incDataInTransaction(Long entityId) { - eventuateTransactionalTemplate.executeInTransaction(() -> { - incData(entityId); - return null; - }); + public EventuateTransactionTemplate getEventuateTransactionalTemplate() { + return eventuateTransactionalTemplate; } @Override - public long getDataInTransaction(Long entityId) { - return eventuateTransactionalTemplate.executeInTransaction(() -> { - return getData(entityId); - }); + public TestEntityRepository getTestEntityRepository() { + return testEntityRepository; } } diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/resources/application.yml b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/resources/application.yml index b7128afd..6aeb7c6b 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/resources/application.yml +++ b/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/resources/application.yml @@ -7,7 +7,7 @@ datasources: jpa: default: packages-to-scan: - - 'io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking' + - 'io.eventuate.tram.jdbc.optimistic.locking.common.test' properties: hibernate: hbm2ddl: diff --git a/eventuate-tram-optimistic-locking-common-test/build.gradle b/eventuate-tram-optimistic-locking-common-test/build.gradle new file mode 100644 index 00000000..d403348c --- /dev/null +++ b/eventuate-tram-optimistic-locking-common-test/build.gradle @@ -0,0 +1,8 @@ +dependencies { + compile project(":eventuate-tram-consumer-common") + compile project(":eventuate-tram-consumer-common") + compile "io.eventuate.common:eventuate-common-jdbc:$eventuateCommonVersion" + compile 'javax.persistence:javax.persistence-api:2.2' + + compile "junit:junit:4.12" +} diff --git a/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractEventuateOptimisticLockingTest.java b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractEventuateOptimisticLockingTest.java new file mode 100644 index 00000000..db450a41 --- /dev/null +++ b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractEventuateOptimisticLockingTest.java @@ -0,0 +1,46 @@ +package io.eventuate.tram.jdbc.optimistic.locking.common.test; + +import io.eventuate.tram.consumer.common.MessageHandlerDecorator; +import org.junit.Assert; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; + +public abstract class AbstractEventuateOptimisticLockingTest { + + private static final int UPDATE_THREADS = 3; + + private AtomicInteger attempts = new AtomicInteger(0); + + private CountDownLatch countDownLatch = new CountDownLatch(UPDATE_THREADS); + + protected abstract AbstractTestEntityService testEntityService(); + + public void shouldRetryOnLockException() throws InterruptedException { + + long testEntityId = testEntityService().createTestEntityInTransaction(); + + for (int i = 0; i < UPDATE_THREADS; i++) updateEntity(testEntityId); + + countDownLatch.await(); + + Assert.assertTrue(attempts.get() > UPDATE_THREADS); + Assert.assertEquals(UPDATE_THREADS, testEntityService().getDataInTransaction(testEntityId)); + } + + public abstract MessageHandlerDecorator getOptimisticLockingDecorator(); + + private void updateEntity(Long testEntityId) { + new Thread(() -> { + + getOptimisticLockingDecorator().accept(null, subscriberIdAndMessage -> { + attempts.incrementAndGet(); + + testEntityService().incDataInTransaction(testEntityId); + }); + + countDownLatch.countDown(); + + }).start(); + } +} \ No newline at end of file diff --git a/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityService.java b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityService.java new file mode 100644 index 00000000..69ff57bb --- /dev/null +++ b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityService.java @@ -0,0 +1,36 @@ +package io.eventuate.tram.jdbc.optimistic.locking.common.test; + +public abstract class AbstractTestEntityService { + + public abstract Long createTestEntityInTransaction(); + public abstract void incDataInTransaction(Long entityId); + public abstract long getDataInTransaction(Long entityId); + + public Long createTestEntity() { + TestEntity testEntity = new TestEntity(); + getTestEntityRepository().persist(testEntity); + return testEntity.getId(); + } + + public void incData(Long entityId) { + TestEntity testEntity = getTestEntityRepository().find(entityId); + testEntity.setData(testEntity.getData() + 1); + sleep(); + getTestEntityRepository().persist(testEntity); + } + + public long getData(Long entityId) { + TestEntity testEntity = getTestEntityRepository().find(entityId); + return testEntity.getData(); + } + + public abstract TestEntityRepository getTestEntityRepository(); + + private void sleep() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityServiceTransactionTemplate.java b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityServiceTransactionTemplate.java new file mode 100644 index 00000000..84631160 --- /dev/null +++ b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/AbstractTestEntityServiceTransactionTemplate.java @@ -0,0 +1,28 @@ +package io.eventuate.tram.jdbc.optimistic.locking.common.test; + +import io.eventuate.common.jdbc.EventuateTransactionTemplate; + +public abstract class AbstractTestEntityServiceTransactionTemplate extends AbstractTestEntityService { + + @Override + public Long createTestEntityInTransaction() { + return getEventuateTransactionalTemplate().executeInTransaction(this::createTestEntity); + } + + @Override + public void incDataInTransaction(Long entityId) { + getEventuateTransactionalTemplate().executeInTransaction(() -> { + incData(entityId); + return null; + }); + } + + @Override + public long getDataInTransaction(Long entityId) { + return getEventuateTransactionalTemplate().executeInTransaction(() -> { + return getData(entityId); + }); + } + + public abstract EventuateTransactionTemplate getEventuateTransactionalTemplate(); +} diff --git a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntity.java b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntity.java similarity index 54% rename from eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntity.java rename to eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntity.java index 60b1cdbc..84e20a75 100644 --- a/eventuate-tram-micronaut-spring-jdbc-optimistic-locking/src/test/java/io/eventuate/tram/micronaut/spring/jdbc/optimistic/locking/TestEntity.java +++ b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntity.java @@ -1,6 +1,13 @@ -package io.eventuate.tram.micronaut.spring.jdbc.optimistic.locking; +package io.eventuate.tram.jdbc.optimistic.locking.common.test; -import javax.persistence.*; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Version; @Entity @Table(name="Customer") diff --git a/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntityRepository.java b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntityRepository.java new file mode 100644 index 00000000..fa341daa --- /dev/null +++ b/eventuate-tram-optimistic-locking-common-test/src/main/java/io/eventuate/tram/jdbc/optimistic/locking/common/test/TestEntityRepository.java @@ -0,0 +1,7 @@ +package io.eventuate.tram.jdbc.optimistic.locking.common.test; + +public interface TestEntityRepository { + TestEntity find(Long entityId); + + void persist(TestEntity testEntity); +} diff --git a/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java b/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java index f1c4d8f8..4e11a7ac 100644 --- a/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java +++ b/eventuate-tram-spring-cloud-sleuth-integration/src/test/java/io/eventuate/tram/spring/cloudsleuthintegration/test/SpringCloudSleuthIntegrationTest.java @@ -1,7 +1,6 @@ package io.eventuate.tram.spring.cloudsleuthintegration.test; -import io.eventuate.common.common.spring.jdbc.EventuateSpringTransactionTemplate; -import io.eventuate.common.jdbc.EventuateTransactionTemplate; +import io.eventuate.common.spring.jdbc.EventuateTransactionTemplateConfiguration; import io.eventuate.tram.spring.inmemory.TramInMemoryConfiguration; import io.eventuate.util.test.async.Eventually; import org.junit.Test; @@ -19,7 +18,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.transaction.support.TransactionTemplate; import org.springframework.web.client.RestTemplate; import java.util.List; @@ -36,19 +34,13 @@ public class SpringCloudSleuthIntegrationTest { @Configuration @SpringBootApplication - @Import({TramInMemoryConfiguration.class}) + @Import({TramInMemoryConfiguration.class, EventuateTransactionTemplateConfiguration.class}) static class TestConfiguration { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } - - @Bean - public EventuateTransactionTemplate eventuateTransactionTemplate(TransactionTemplate transactionTemplate) { - return new EventuateSpringTransactionTemplate(transactionTemplate); - } - } @Value("${spring.zipkin.baseUrl}") diff --git a/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java b/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java index 44251fa1..0a13270c 100644 --- a/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java +++ b/eventuate-tram-spring-in-memory/src/test/java/io/eventuate/tram/spring/inmemory/InMemoryMessageProducerTest.java @@ -1,7 +1,6 @@ package io.eventuate.tram.spring.inmemory; -import io.eventuate.common.common.spring.jdbc.EventuateSpringTransactionTemplate; -import io.eventuate.common.jdbc.EventuateTransactionTemplate; +import io.eventuate.common.spring.jdbc.EventuateTransactionTemplateConfiguration; import io.eventuate.tram.messaging.consumer.MessageConsumer; import io.eventuate.tram.messaging.producer.MessageProducer; import io.eventuate.tram.inmemory.test.AbstractInMemoryMessageProducerTest; @@ -11,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; @@ -24,12 +22,8 @@ public class InMemoryMessageProducerTest extends AbstractInMemoryMessageProducerTest { @Configuration @EnableAutoConfiguration - @Import({TramInMemoryConfiguration.class}) + @Import({TramInMemoryConfiguration.class, EventuateTransactionTemplateConfiguration.class}) public static class InMemoryMessagingTestConfiguration { - @Bean - public EventuateTransactionTemplate eventuateTransactionTemplate(TransactionTemplate transactionTemplate) { - return new EventuateSpringTransactionTemplate(transactionTemplate); - } } @Autowired diff --git a/eventuate-tram-spring-optimistic-locking/build.gradle b/eventuate-tram-spring-optimistic-locking/build.gradle index a33997a7..4f344e72 100644 --- a/eventuate-tram-spring-optimistic-locking/build.gradle +++ b/eventuate-tram-spring-optimistic-locking/build.gradle @@ -2,6 +2,11 @@ apply plugin: PublicModulePlugin dependencies { compile project (":eventuate-tram-consumer-common") + compile project(":eventuate-tram-optimistic-locking-common-test") compile "org.springframework.boot:spring-boot-starter-jdbc:$springBootVersion" compile 'org.springframework.retry:spring-retry:1.2.4.RELEASE' + compile "io.eventuate.common:eventuate-common-spring-jdbc:$eventuateCommonVersion" + compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootCdcVersion" + + testCompile "org.springframework.boot:spring-boot-starter-test:$springBootCdcVersion" } \ No newline at end of file diff --git a/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecorator.java b/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecorator.java index fbeb0a83..1c761818 100644 --- a/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecorator.java +++ b/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecorator.java @@ -13,7 +13,7 @@ public class OptimisticLockingDecorator implements MessageHandlerDecorator, Ordered { @Override - @Retryable(value = OptimisticLockingFailureException.class, + @Retryable(value = {OptimisticLockingFailureException.class}, maxAttempts = 10, backoff = @Backoff(delay = 100)) public void accept(SubscriberIdAndMessage subscriberIdAndMessage, MessageHandlerDecoratorChain messageHandlerDecoratorChain) { diff --git a/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecoratorConfiguration.java b/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecoratorConfiguration.java index 188680a3..1d523b79 100644 --- a/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecoratorConfiguration.java +++ b/eventuate-tram-spring-optimistic-locking/src/main/java/io/eventuate/tram/spring/optimisticlocking/OptimisticLockingDecoratorConfiguration.java @@ -2,8 +2,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.retry.annotation.EnableRetry; @Configuration +@EnableRetry public class OptimisticLockingDecoratorConfiguration { @Bean public OptimisticLockingDecorator optimisticLockingDecorator() { diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/AbstractEventuateSpringOptimisticLockingTest.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/AbstractEventuateSpringOptimisticLockingTest.java new file mode 100644 index 00000000..f796c1fb --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/AbstractEventuateSpringOptimisticLockingTest.java @@ -0,0 +1,16 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.tram.consumer.common.MessageHandlerDecorator; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractEventuateOptimisticLockingTest; +import org.springframework.beans.factory.annotation.Autowired; + +abstract public class AbstractEventuateSpringOptimisticLockingTest extends AbstractEventuateOptimisticLockingTest { + + @Autowired + private OptimisticLockingDecorator optimisticLockingDecorator; + + @Override + public MessageHandlerDecorator getOptimisticLockingDecorator() { + return optimisticLockingDecorator; + } +} \ No newline at end of file diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithAnnotationTransactionTest.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithAnnotationTransactionTest.java new file mode 100644 index 00000000..e8666909 --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithAnnotationTransactionTest.java @@ -0,0 +1,39 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = EventuateSpringOptimisticLockingWithAnnotationTransactionTest.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) +public class EventuateSpringOptimisticLockingWithAnnotationTransactionTest extends AbstractEventuateSpringOptimisticLockingTest { + + @Configuration + @Import({OptimisticLockingDecoratorConfiguration.class, TestEntityRepositoryConfiguration.class}) + public static class Config { + @Bean + public TestEntityServiceTransactionAnnotation testEntityServiceTransactionAnnotation() { + return new TestEntityServiceTransactionAnnotation(); + } + } + + @Autowired + private TestEntityServiceTransactionAnnotation testEntityService; + + @Override + protected AbstractTestEntityService testEntityService() { + return testEntityService; + } + + @Override + @Test + public void shouldRetryOnLockException() throws InterruptedException { + super.shouldRetryOnLockException(); + } +} \ No newline at end of file diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithTransactionTemplateTransactionTest.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithTransactionTemplateTransactionTest.java new file mode 100644 index 00000000..25babbaa --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/EventuateSpringOptimisticLockingWithTransactionTemplateTransactionTest.java @@ -0,0 +1,39 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = EventuateSpringOptimisticLockingWithTransactionTemplateTransactionTest.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) +public class EventuateSpringOptimisticLockingWithTransactionTemplateTransactionTest extends AbstractEventuateSpringOptimisticLockingTest { + + @Configuration + @Import({OptimisticLockingDecoratorConfiguration.class, TestEntityRepositoryConfiguration.class}) + public static class Config { + @Bean + public TestEntityServiceTransactionTemplate testEntityServiceTransactionTemplate() { + return new TestEntityServiceTransactionTemplate(); + } + } + + @Autowired + private TestEntityServiceTransactionTemplate testEntityService; + + @Override + protected AbstractTestEntityService testEntityService() { + return testEntityService; + } + + @Override + @Test + public void shouldRetryOnLockException() throws InterruptedException { + super.shouldRetryOnLockException(); + } +} \ No newline at end of file diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryConfiguration.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryConfiguration.java new file mode 100644 index 00000000..c7513ae6 --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryConfiguration.java @@ -0,0 +1,20 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.common.spring.jdbc.EventuateTransactionTemplateConfiguration; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@EnableAutoConfiguration +@EntityScan(basePackages = "io.eventuate.tram.jdbc.optimistic.locking.common.test") +@Import(EventuateTransactionTemplateConfiguration.class) +public class TestEntityRepositoryConfiguration { + @Bean + public TestEntityRepository testEntityRepository() { + return new TestEntityRepositoryImpl(); + } +} diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryImpl.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryImpl.java new file mode 100644 index 00000000..e2c35fc1 --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityRepositoryImpl.java @@ -0,0 +1,21 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntity; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; +import org.springframework.beans.factory.annotation.Autowired; + +public class TestEntityRepositoryImpl implements TestEntityRepository { + + @Autowired + private TestEntitySpringRepository testEntitySpringRepository; + + @Override + public TestEntity find(Long entityId) { + return testEntitySpringRepository.findById(entityId).orElse(null); + } + + @Override + public void persist(TestEntity testEntity) { + testEntitySpringRepository.save(testEntity); + } +} diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionAnnotation.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionAnnotation.java new file mode 100644 index 00000000..df05891e --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionAnnotation.java @@ -0,0 +1,35 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityService; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +public class TestEntityServiceTransactionAnnotation extends AbstractTestEntityService { + + @Autowired + private TestEntityRepository testEntityRepository; + + @Transactional + @Override + public Long createTestEntityInTransaction() { + return createTestEntity(); + } + + @Transactional + @Override + public void incDataInTransaction(Long entityId) { + incData(entityId); + } + + @Transactional + @Override + public long getDataInTransaction(Long entityId) { + return getData(entityId); + } + + @Override + public TestEntityRepository getTestEntityRepository() { + return testEntityRepository; + } +} diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionTemplate.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionTemplate.java new file mode 100644 index 00000000..d585bf7b --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntityServiceTransactionTemplate.java @@ -0,0 +1,25 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.common.jdbc.EventuateTransactionTemplate; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.AbstractTestEntityServiceTransactionTemplate; +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntityRepository; +import org.springframework.beans.factory.annotation.Autowired; + +public class TestEntityServiceTransactionTemplate extends AbstractTestEntityServiceTransactionTemplate { + + @Autowired + private TestEntityRepository testEntityRepository; + + @Autowired + private EventuateTransactionTemplate eventuateTransactionalTemplate; + + @Override + public EventuateTransactionTemplate getEventuateTransactionalTemplate() { + return eventuateTransactionalTemplate; + } + + @Override + public TestEntityRepository getTestEntityRepository() { + return testEntityRepository; + } +} diff --git a/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntitySpringRepository.java b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntitySpringRepository.java new file mode 100755 index 00000000..8332d43f --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/java/io/eventuate/tram/spring/optimisticlocking/TestEntitySpringRepository.java @@ -0,0 +1,7 @@ +package io.eventuate.tram.spring.optimisticlocking; + +import io.eventuate.tram.jdbc.optimistic.locking.common.test.TestEntity; +import org.springframework.data.repository.PagingAndSortingRepository; + +public interface TestEntitySpringRepository extends PagingAndSortingRepository { +} diff --git a/eventuate-tram-spring-optimistic-locking/src/test/resources/application-mssql.properties b/eventuate-tram-spring-optimistic-locking/src/test/resources/application-mssql.properties new file mode 100644 index 00000000..d61e4995 --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/resources/application-mssql.properties @@ -0,0 +1,4 @@ +spring.datasource.url=jdbc:sqlserver://${DOCKER_HOST_IP:localhost}:1433;databaseName=eventuate +spring.datasource.username=sa +spring.datasource.password=Eventuate123! +spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver \ No newline at end of file diff --git a/eventuate-tram-spring-optimistic-locking/src/test/resources/application-postgres.properties b/eventuate-tram-spring-optimistic-locking/src/test/resources/application-postgres.properties new file mode 100644 index 00000000..ca2da369 --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/resources/application-postgres.properties @@ -0,0 +1,5 @@ +spring.datasource.url=jdbc:postgresql://${DOCKER_HOST_IP:localhost}/eventuate +spring.datasource.username=eventuate +spring.datasource.password=eventuate +spring.datasource.driver-class-name=org.postgresql.Driver +spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file diff --git a/eventuate-tram-spring-optimistic-locking/src/test/resources/application.properties b/eventuate-tram-spring-optimistic-locking/src/test/resources/application.properties new file mode 100644 index 00000000..36991d4f --- /dev/null +++ b/eventuate-tram-spring-optimistic-locking/src/test/resources/application.properties @@ -0,0 +1,5 @@ +spring.datasource.url=jdbc:mysql://${DOCKER_HOST_IP:localhost}/eventuate +spring.datasource.username=mysqluser +spring.datasource.password=mysqlpw +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.generate-ddl=true diff --git a/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java b/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java index be859c67..78409aaa 100644 --- a/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java +++ b/eventuate-tram-testing-support/src/test/java/io/eventuate/tram/testing/MessageTrackerTest.java @@ -1,7 +1,6 @@ package io.eventuate.tram.testing; -import io.eventuate.common.common.spring.jdbc.EventuateSpringTransactionTemplate; -import io.eventuate.common.jdbc.EventuateTransactionTemplate; +import io.eventuate.common.spring.jdbc.EventuateTransactionTemplateConfiguration; import io.eventuate.tram.commands.common.Command; import io.eventuate.tram.commands.producer.CommandProducer; import io.eventuate.tram.spring.commands.producer.TramCommandProducerConfiguration; @@ -19,7 +18,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.transaction.support.TransactionTemplate; import java.util.Collections; import java.util.Set; @@ -35,18 +33,16 @@ public class MessageTrackerTest { @Configuration @EnableAutoConfiguration - @Import({TramInMemoryConfiguration.class, TramCommandProducerConfiguration.class, TramEventsPublisherConfiguration.class}) + @Import({TramInMemoryConfiguration.class, + TramCommandProducerConfiguration.class, + TramEventsPublisherConfiguration.class, + EventuateTransactionTemplateConfiguration.class}) public static class MessageTrackerTestConfiguration { @Bean public MessageTracker messageTracker(MessageConsumer messageConsumer) { return new MessageTracker(channels, messageConsumer); } - - @Bean - public EventuateTransactionTemplate eventuateTransactionTemplate(TransactionTemplate transactionTemplate) { - return new EventuateSpringTransactionTemplate(transactionTemplate); - } } @Autowired diff --git a/settings.gradle b/settings.gradle index 61573865..9a3ce376 100644 --- a/settings.gradle +++ b/settings.gradle @@ -48,6 +48,7 @@ include 'eventuate-tram-consumer-rabbitmq' include 'eventuate-tram-consumer-redis' include 'eventuate-tram-spring-optimistic-locking' include 'eventuate-tram-micronaut-spring-jdbc-optimistic-locking' +include 'eventuate-tram-optimistic-locking-common-test' include 'eventuate-tram-spring-messaging-starter' include 'eventuate-tram-spring-events-publisher-starter'