diff --git a/pluto-server/pom.xml b/pluto-server/pom.xml index d9f7b12ec1baaf19ab3e0742ee73b480a16a5e8a..1a6ac7b29c094e1e28ba302f0582eeecee2b3326 100644 --- a/pluto-server/pom.xml +++ b/pluto-server/pom.xml @@ -27,9 +27,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <mongock.version>5.0.35</mongock.version> - <mongodb.testcontainer.version>1.15.3</mongodb.testcontainer.version> - <solr.testcontainer.version>1.16.2</solr.testcontainer.version> - <elasticsearch.testcontainer.version>1.17.3</elasticsearch.testcontainer.version> + <testcontainer.version>1.17.3</testcontainer.version> </properties> <dependencies> @@ -92,10 +90,11 @@ </dependency> <dependency> - <groupId>org.springframework.data</groupId> - <artifactId>spring-data-elasticsearch</artifactId> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> + <!-- aspectJ --> <dependency> <groupId>org.aspectj</groupId> @@ -216,19 +215,19 @@ <dependency> <groupId>org.testcontainers</groupId> <artifactId>mongodb</artifactId> - <version>${mongodb.testcontainer.version}</version> + <version>${testcontainer.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>solr</artifactId> - <version>${solr.testcontainer.version}</version> + <version>${testcontainer.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>elasticsearch</artifactId> - <version>${elasticsearch.testcontainer.version}</version> + <version>${testcontainer.version}</version> <scope>test</scope> </dependency> diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java index c3e9cbd217f58f9afa146e0d9a328eeecdc56016..db39b754c4c1ac3d3f582feb4d31e6c0ed43466b 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java @@ -7,6 +7,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.security.authentication.AuthenticationTrustResolver; @@ -20,6 +22,8 @@ import io.mongock.runner.springboot.EnableMongock; @EnableAspectJAutoProxy(proxyTargetClass = true) @EnableMongock @ConfigurationPropertiesScan("de.itvsh.ozg.pluto.common.*") +@EnableMongoRepositories(basePackages = { "de.itvsh.ozg.pluto.vorgang", "de.itvsh.ozg.pluto.attached_item", "de.itvsh.ozg.pluto.command" }) +@EnableElasticsearchRepositories(basePackages = "de.itvsh.ozg.pluto.common.elastic") public class PlutoServerApplication { public static void main(String[] args) { diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexInitializer.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexInitializer.java new file mode 100644 index 0000000000000000000000000000000000000000..711f0653052747149492b04ed999656954a92ae4 --- /dev/null +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexInitializer.java @@ -0,0 +1,26 @@ +package de.itvsh.ozg.pluto.common.elastic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import de.itvsh.ozg.pluto.vorgang.VorgangService; + +@Component +@ConditionalOnProperty(prefix = "kop.elasticsearch", name = "initEnabled") +@Async +public class ElasticsearchIndexInitializer implements ApplicationListener<ContextRefreshedEvent> { + @Autowired + private VorgangService vorgangService; + + @Autowired + private ElasticsearchService searchService; + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + vorgangService.getAll().forEach(vorgang -> searchService.addVorgang(vorgang)); + } +} diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchProperties.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..1fd6b14209d8eaa2d088dd49907aa1292823cc2b --- /dev/null +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchProperties.java @@ -0,0 +1,15 @@ +package de.itvsh.ozg.pluto.common.elastic; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@ConfigurationProperties(prefix = "kop.elasticsearch") +public class ElasticsearchProperties { + private String host; + private String collectionName; + private boolean initEnabled = false; +} diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..ac8621f0cd46f1d9a6cbd9b1e1f33ecd723e5361 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchITCase.java @@ -0,0 +1,24 @@ +package de.itvsh.ozg.pluto.common.elastic; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +import de.itvsh.kop.common.test.DataITCase; +import de.itvsh.kop.common.test.DbInitializer; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Inherited + +@DataITCase +@ContextConfiguration(initializers = { ElasticsearchInitializer.class, DbInitializer.class }) +@ActiveProfiles({ "itcase", "with_db" }) +public @interface ElasticsearchITCase { + +} diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexInitializerITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexInitializerITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..4e41142945a6d2e248e1f4d2d551ac00efe47267 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexInitializerITCase.java @@ -0,0 +1,95 @@ +package de.itvsh.ozg.pluto.common.elastic; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrServerException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +import de.itvsh.kop.common.test.DbInitializer; +import de.itvsh.kop.common.test.ITCase; +import de.itvsh.ozg.pluto.vorgang.Vorgang; +import de.itvsh.ozg.pluto.vorgang.VorgangService; +import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory; + +class ElasticsearchIndexInitializerITCase { + private static final int FOR_500_MS = 500; + + @Nested + @ITCase + class TestNotConfigured { + @MockBean + private ElasticsearchService elasticsearchService; + + @MockBean + private VorgangService vorgangService; + + @Test + void shouldNotStartIndexer() throws SolrServerException, IOException { + verify(vorgangService, after(FOR_500_MS).never()).getAll(); + verify(elasticsearchService, after(FOR_500_MS).never()).addVorgang(any()); + } + } + + @Nested + @ElasticsearchITCase + class TestConfiguredNotEnabled { + + @MockBean + private ElasticsearchService elasticService; + + @MockBean + private VorgangService vorgangService; + + @Test + void shouldNotStartIndexer() throws SolrServerException, IOException { + verify(vorgangService, after(FOR_500_MS).never()).getAll(); + verify(elasticService, after(FOR_500_MS).never()).updateVorgang(any()); + } + } + + @Nested + @ITCase + @ContextConfiguration(initializers = { DbInitializer.class, ElasticsearchIndexerEnabledInitializer.class }) + @ActiveProfiles({ "itcase", "with_db" }) + class TestConfiguredEnabled { + @MockBean + private ElasticsearchService elasticService; + + @Autowired + private ElasticsearchIndexInitializer elasticsearchInitializer; + + @Autowired + private MongoOperations mongoOperations; + + @BeforeEach + void init() { + mongoOperations.dropCollection(Vorgang.COLLECTION_NAME); + + mongoOperations.createCollection(Vorgang.COLLECTION_NAME); + } + + @Test + void shouldNotStartIndexerWhenNoVorgang() throws SolrServerException, IOException { + verify(elasticService, after(FOR_500_MS).never()).addVorgang(any()); + } + + @Test + void shouldStartIndexer() throws SolrServerException, IOException { + mongoOperations.save(VorgangTestFactory.create()); + + elasticsearchInitializer.onApplicationEvent(null); + + verify(elasticService, after(FOR_500_MS)).addVorgang(any()); + } + } +} diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java index a8024d2e5cd6f395b19758c019423d7f7614aa2a..8f6ec24da6c52926df737e711b06de5da1613087 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchIndexerEnabledInitializer.java @@ -4,11 +4,11 @@ import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ConfigurableApplicationContext; import org.testcontainers.elasticsearch.ElasticsearchContainer; -public class ElasticsearchIndexerEnabledInitializer extends ElasticsearchInitializer { +class ElasticsearchIndexerEnabledInitializer extends ElasticsearchInitializer { @Override protected void setProperties(ElasticsearchContainer container, ConfigurableApplicationContext applicationContext) { super.setProperties(container, applicationContext); - TestPropertyValues.of("kop.elasticsearch.initEnabled=true"); + TestPropertyValues.of("kop.elasticsearch.initEnabled=true").applyTo(applicationContext.getEnvironment()); } } diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java index b8ed48af0743c0bbe9fdef40b657842350dd13bb..8180a45a8e3604b950c4a83fc34c09d3cb8e3b51 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchInitializer.java @@ -4,18 +4,20 @@ import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.utility.DockerImageName; import lombok.AccessLevel; import lombok.Getter; -public class ElasticsearchInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { - private static final String ELASTICSEARCH_VERSIION = "docker.elastic.co/elasticsearch/elasticsearch:8.3.2"; +class ElasticsearchInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { + private static final String ELASTICSEARCH_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch"; + private static final String ELASTICSEARCH_VERSION = "8.3.2"; @Getter(value = AccessLevel.PROTECTED) private ElasticsearchContainer elasticsearchContainer; @Override public void initialize(ConfigurableApplicationContext applicationContext) { - elasticsearchContainer = new ElasticsearchContainer(ELASTICSEARCH_VERSIION); + elasticsearchContainer = new ElasticsearchContainer(DockerImageName.parse(ELASTICSEARCH_IMAGE).withTag(ELASTICSEARCH_VERSION)); elasticsearchContainer.start(); setProperties(elasticsearchContainer, applicationContext); diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchServiceITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchServiceITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..d71b50762d7dd3992b8f9079de8d2c3e2954e1c9 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/elastic/ElasticsearchServiceITCase.java @@ -0,0 +1,55 @@ +package de.itvsh.ozg.pluto.common.elastic; + +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.util.Optional; + +import org.apache.solr.client.solrj.SolrServerException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.mongodb.core.MongoOperations; + +import de.itvsh.ozg.pluto.command.Command; +import de.itvsh.ozg.pluto.command.CommandService; +import de.itvsh.ozg.pluto.command.CommandTestFactory; +import de.itvsh.ozg.pluto.vorgang.Vorgang; +import de.itvsh.ozg.pluto.vorgang.VorgangService; + +@ElasticsearchITCase +public class ElasticsearchServiceITCase { + @Autowired + private ElasticsearchService elasticsearchService; + + @Autowired + private VorgangService vorgangService; + + @Autowired + private MongoOperations mongoOperations; + + @MockBean + private CommandService commandService; + + @Autowired + private ElasticsearchProperties elasticsearchProperties; + + @BeforeEach + void init() { + Command cmd = CommandTestFactory.createBuilder().build(); + when(commandService.findCommand(CommandTestFactory.ID)).thenReturn(Optional.of(cmd)); + + mongoOperations.remove(Vorgang.class); + } + + @Nested + class TestAddVorgang { + @Test + void shouldAdd() throws SolrServerException, IOException { + elasticsearchService.addVorgang(null); + } + } + +}