From 8a022f72b5929e6ef6d7cb93263bf71b67fd7248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Henninger?= Date: Fri, 12 Jun 2026 16:29:53 +0200 Subject: [PATCH 1/5] fix: add transactional annotation on saveAll --- .../insee/genesis/configuration/MongoConfig.java | 16 ++++++++++++++++ .../adapter/SurveyUnitMongoAdapter.java | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 src/main/java/fr/insee/genesis/configuration/MongoConfig.java diff --git a/src/main/java/fr/insee/genesis/configuration/MongoConfig.java b/src/main/java/fr/insee/genesis/configuration/MongoConfig.java new file mode 100644 index 000000000..6f0a91cb2 --- /dev/null +++ b/src/main/java/fr/insee/genesis/configuration/MongoConfig.java @@ -0,0 +1,16 @@ +package fr.insee.genesis.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.MongoTransactionManager; + +@Configuration +public class MongoConfig { + + @Bean + MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { + return new MongoTransactionManager(dbFactory); + } + +} diff --git a/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java b/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java index 99a01737a..79c348162 100644 --- a/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java +++ b/src/main/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapter.java @@ -19,6 +19,7 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Service; import tools.jackson.databind.json.JsonMapper; +import org.springframework.transaction.annotation.Transactional; import java.time.Instant; import java.time.LocalDateTime; @@ -45,6 +46,7 @@ public SurveyUnitMongoAdapter(SurveyUnitMongoDBRepository mongoRepository, Mongo } @Override + @Transactional public void saveAll(List surveyUnitModels) { List suList = SurveyUnitDocumentMapper.INSTANCE.listModelToListDocument(surveyUnitModels); mongoRepository.insert(suList); From 7a49468c19346f26f208bc70f07a0d74936a1907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Henninger?= Date: Fri, 12 Jun 2026 17:15:09 +0200 Subject: [PATCH 2/5] test: check the presence of @transactional annotation --- .../adapter/SurveyUnitMongoAdapterTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java b/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java index d7aaf8ee4..ea15d6aca 100644 --- a/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java +++ b/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java @@ -18,7 +18,9 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.transaction.annotation.Transactional; +import java.lang.reflect.Method; import java.time.Instant; import java.time.LocalDateTime; import java.util.List; @@ -90,6 +92,15 @@ void saveAll_shouldMapAllModels() { verify(mongoRepository).insert(captor.capture()); assertThat(captor.getValue()).hasSize(3); } + + @Test + @DisplayName("saveAll() should be annotated with @Transactional") + void saveAll_shouldBeTransactional() throws NoSuchMethodException { + Method method = SurveyUnitMongoAdapter.class.getMethod("saveAll", List.class); + assertThat(method.isAnnotationPresent(Transactional.class)).isTrue(); + } + + } @Nested From 094e970dc573aad607446a81f2bf9db9e4dc3a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Henninger?= Date: Fri, 12 Jun 2026 17:16:44 +0200 Subject: [PATCH 3/5] chore: add a empty line between tests --- .../infrastructure/adapter/SurveyUnitMongoAdapterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java b/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java index ea15d6aca..a4fecdf7f 100644 --- a/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java +++ b/src/test/java/fr/insee/genesis/infrastructure/adapter/SurveyUnitMongoAdapterTest.java @@ -92,7 +92,7 @@ void saveAll_shouldMapAllModels() { verify(mongoRepository).insert(captor.capture()); assertThat(captor.getValue()).hasSize(3); } - + @Test @DisplayName("saveAll() should be annotated with @Transactional") void saveAll_shouldBeTransactional() throws NoSuchMethodException { From 371faee2634f303d86b6db73d0010294783f786c Mon Sep 17 00:00:00 2001 From: Hajarel-moukh Date: Thu, 18 Jun 2026 10:40:49 +0200 Subject: [PATCH 4/5] fix tests --- .../insee/genesis/configuration/MongoConfig.java | 2 ++ .../genesis/TransactionManagerTestConfig.java | 15 +++++++++++++++ .../controller/IntegrationTestAbstract.java | 3 +++ .../rest/responses/RawResponseControllerTest.java | 3 ++- .../rest/responses/ResponseControllerTest.java | 3 ++- 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/test/java/fr/insee/genesis/TransactionManagerTestConfig.java diff --git a/src/main/java/fr/insee/genesis/configuration/MongoConfig.java b/src/main/java/fr/insee/genesis/configuration/MongoConfig.java index 6f0a91cb2..c65f0571d 100644 --- a/src/main/java/fr/insee/genesis/configuration/MongoConfig.java +++ b/src/main/java/fr/insee/genesis/configuration/MongoConfig.java @@ -1,5 +1,6 @@ package fr.insee.genesis.configuration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; @@ -9,6 +10,7 @@ public class MongoConfig { @Bean + @ConditionalOnBean(MongoDatabaseFactory.class) MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } diff --git a/src/test/java/fr/insee/genesis/TransactionManagerTestConfig.java b/src/test/java/fr/insee/genesis/TransactionManagerTestConfig.java new file mode 100644 index 000000000..96811f8b2 --- /dev/null +++ b/src/test/java/fr/insee/genesis/TransactionManagerTestConfig.java @@ -0,0 +1,15 @@ +package fr.insee.genesis; + +import org.mockito.Mockito; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.transaction.PlatformTransactionManager; + +@TestConfiguration +public class TransactionManagerTestConfig { + + @Bean + PlatformTransactionManager transactionManager() { + return Mockito.mock(PlatformTransactionManager.class); + } +} diff --git a/src/test/java/fr/insee/genesis/controller/IntegrationTestAbstract.java b/src/test/java/fr/insee/genesis/controller/IntegrationTestAbstract.java index 338e14f00..3d81c5e85 100644 --- a/src/test/java/fr/insee/genesis/controller/IntegrationTestAbstract.java +++ b/src/test/java/fr/insee/genesis/controller/IntegrationTestAbstract.java @@ -1,5 +1,6 @@ package fr.insee.genesis.controller; +import fr.insee.genesis.TransactionManagerTestConfig; import fr.insee.genesis.controller.utils.ControllerUtils; import fr.insee.genesis.domain.ports.spi.SurveyUnitQualityToolPort; import fr.insee.genesis.infrastructure.repository.ContextualExternalVariableMongoDBRepository; @@ -18,6 +19,7 @@ import org.springframework.boot.mongodb.autoconfigure.MongoAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; +import org.springframework.context.annotation.Import; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; @@ -35,6 +37,7 @@ "logging.level.=DEBUG" }) @EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, DataMongoAutoConfiguration.class}) +@Import(TransactionManagerTestConfig.class) public abstract class IntegrationTestAbstract { @Autowired protected MockMvc mockMvc; diff --git a/src/test/java/fr/insee/genesis/controller/rest/responses/RawResponseControllerTest.java b/src/test/java/fr/insee/genesis/controller/rest/responses/RawResponseControllerTest.java index b32bad06f..9199da8c2 100644 --- a/src/test/java/fr/insee/genesis/controller/rest/responses/RawResponseControllerTest.java +++ b/src/test/java/fr/insee/genesis/controller/rest/responses/RawResponseControllerTest.java @@ -1,5 +1,6 @@ package fr.insee.genesis.controller.rest.responses; +import fr.insee.genesis.TransactionManagerTestConfig; import fr.insee.genesis.configuration.auth.security.DefaultSecurityConfig; import fr.insee.genesis.domain.model.surveyunit.Mode; import fr.insee.genesis.domain.model.surveyunit.rawdata.DataProcessResult; @@ -59,7 +60,7 @@ @TestPropertySource(properties = { "fr.insee.genesis.authentication=NONE" }) -@Import({DefaultSecurityConfig.class}) +@Import({DefaultSecurityConfig.class, TransactionManagerTestConfig.class}) @ActiveProfiles("test") @AutoConfigureMockMvc @EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, DataMongoAutoConfiguration.class}) diff --git a/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java b/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java index 5238e827b..f575a23f8 100644 --- a/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java +++ b/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java @@ -2,6 +2,7 @@ import fr.insee.bpm.metadata.model.MetadataModel; import fr.insee.bpm.metadata.model.VariablesMap; +import fr.insee.genesis.TransactionManagerTestConfig; import fr.insee.genesis.configuration.auth.security.DefaultSecurityConfig; import fr.insee.genesis.controller.dto.SurveyUnitDto; import fr.insee.genesis.controller.dto.SurveyUnitSimplifiedDto; @@ -59,7 +60,7 @@ @TestPropertySource(properties = { "fr.insee.genesis.authentication=NONE" }) -@Import({DefaultSecurityConfig.class}) +@Import({DefaultSecurityConfig.class, TransactionManagerTestConfig.class}) @ActiveProfiles("test") @AutoConfigureMockMvc @EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, DataMongoAutoConfiguration.class}) From e6e07c49d4444ab278f8adfd0abb7e630921c8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Henninger?= Date: Fri, 19 Jun 2026 17:17:16 +0200 Subject: [PATCH 5/5] fix: register MongoTransactionManager reliably in prod environment --- .../java/fr/insee/genesis/configuration/MongoConfig.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/insee/genesis/configuration/MongoConfig.java b/src/main/java/fr/insee/genesis/configuration/MongoConfig.java index c65f0571d..8e693270d 100644 --- a/src/main/java/fr/insee/genesis/configuration/MongoConfig.java +++ b/src/main/java/fr/insee/genesis/configuration/MongoConfig.java @@ -1,16 +1,17 @@ package fr.insee.genesis.configuration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; @Configuration public class MongoConfig { @Bean - @ConditionalOnBean(MongoDatabaseFactory.class) + @ConditionalOnMissingBean(PlatformTransactionManager.class) MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); }