From b6297aa3833a3a3f5c385e00242fd2766bae1abb Mon Sep 17 00:00:00 2001 From: "Martin W. Kirst" Date: Mon, 9 Aug 2021 14:57:45 +0200 Subject: [PATCH 1/2] The root cause was a broken check for duplicates in the DB. This solution favors creating new ID, based on a composition of partitionId and position. See comments in PR #280 and Issue #278 for more details. Tests are added to show implementation works properly Unfortunately, because of JPA requires an @Id field, a new field was introduced and there's an UPGRADE instruction documented, so people out there would be able to migrate their installations. --- README.md | 6 +- UPGRADE.md | 36 +++++++++++ .../monitor/entity/ElementInstanceEntity.java | 29 ++++++++- .../zeebe/monitor/entity/VariableEntity.java | 41 +++++++++++-- .../repository/ElementInstanceRepository.java | 2 +- .../repository/VariableRepository.java | 2 +- .../importers/ProcessAndElementImporter.java | 29 ++++----- .../zeebe/importers/VariableImporter.java | 27 ++++----- .../ElementInstanceRepositoryTest.java | 48 +++++++++++++++ .../TestContextJpaConfiguration.java | 60 +++++++++++++++++++ .../repository/VariableRepositoryTest.java | 48 +++++++++++++++ .../repository/ZeebeRepositoryTest.java | 18 ++++++ .../monitor/rest/ViewControllerTest.java | 3 + .../ProcessAndElementImporterTest.java | 56 +++++++++++++++++ .../zeebe/importers/VariableImporterTest.java | 48 +++++++++++++++ src/test/resources/application-junittest.yaml | 4 ++ 16 files changed, 417 insertions(+), 40 deletions(-) create mode 100644 UPGRADE.md create mode 100644 src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java create mode 100644 src/test/java/io/zeebe/monitor/repository/TestContextJpaConfiguration.java create mode 100644 src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java create mode 100644 src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java create mode 100644 src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java create mode 100644 src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java create mode 100644 src/test/resources/application-junittest.yaml diff --git a/README.md b/README.md index 27d5b293..7854286a 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,11 @@ The application imports the data from Zeebe using the [Hazelcast exporter](https ![how-it-works](docs/how-it-works.png) -## Install +## Upgrading from prior version + +See [upgrade instructions](./UPGRADE.md) + +## Fresh install ### Docker diff --git a/UPGRADE.md b/UPGRADE.md new file mode 100644 index 00000000..b77e4c4b --- /dev/null +++ b/UPGRADE.md @@ -0,0 +1,36 @@ + +Upgrade documentation for Zeebe Simple Monitor +================================================== + +## Upgrading from v2.0.0 + +Due to some issues with storing variables and element instances, the database structure changed. +Zeebe Simple Monitor will not alter existing database tables automatically, but if you have a PostgreSQL +or other DB running, you need to alter the table structures manually, in order to keep your data. + +Of course, if you use an in-memory DB or do not need to keep prior data, then simply drop all tables and sequences, +and let Zeebe Simple Monitor create them again for you (automatic creation works). + +### Upgrade procedure + +1. stop Zeebe Simple Monitor (v2.0.0) +2. run the SQL script below against your PostgreSQL Database +3. start up Zeebe Simple Monitor (new version) + +```sql +-- part 1, element_instance table changes +ALTER TABLE element_instance ADD COLUMN ID varchar(255); +UPDATE element_instance SET id = (partition_id_::varchar || '-' || position_::varchar) where true; +ALTER TABLE element_instance DROP CONSTRAINT element_instance_pkey; +ALTER TABLE element_instance ADD PRIMARY KEY (id); +CREATE INDEX element_instance_processInstanceKeyIndex ON element_instance (process_instance_key_); +-- part 2, variable table changes +ALTER TABLE variable ADD COLUMN ID varchar(255); +ALTER TABLE variable ADD COLUMN PARTITION_ID_ integer DEFAULT 1; +UPDATE variable SET id = (partition_id_::varchar || '-' || position_::varchar) where true; +ALTER TABLE variable DROP CONSTRAINT variable_pkey; +ALTER TABLE variable ADD PRIMARY KEY (id); +CREATE INDEX variable_processInstanceKeyIndex ON variable (process_instance_key_); +``` +(This SQL was developed and tested using a recent PostgreSQL instance. + You might need to adopt that if you're using another Database) diff --git a/src/main/java/io/zeebe/monitor/entity/ElementInstanceEntity.java b/src/main/java/io/zeebe/monitor/entity/ElementInstanceEntity.java index ba7921f1..2bcd8857 100644 --- a/src/main/java/io/zeebe/monitor/entity/ElementInstanceEntity.java +++ b/src/main/java/io/zeebe/monitor/entity/ElementInstanceEntity.java @@ -15,14 +15,19 @@ */ package io.zeebe.monitor.entity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; +import javax.persistence.*; @Entity(name = "ELEMENT_INSTANCE") +@Table(indexes = { + // performance reason, because we use it in the ElementInstanceRepository.findByProcessInstanceKey() + @Index(name = "element_instance_processInstanceKeyIndex", columnList = "PROCESS_INSTANCE_KEY_"), +}) public class ElementInstanceEntity { @Id + @Column(name = "ID") + private String id; + @Column(name = "POSITION_") private Long position; @@ -53,6 +58,24 @@ public class ElementInstanceEntity { @Column(name = "TIMESTAMP_") private long timestamp; + public String getId() { + return id; + } + + private void setId(final String id) { + // made private, to avoid accidental changes + this.id = id; + } + + public final String getGeneratedIdentifier() { + return this.partitionId + "-" + this.position; + } + + @PrePersist + private void prePersistDeriveIdField() { + setId(getGeneratedIdentifier()); + } + public long getKey() { return key; } diff --git a/src/main/java/io/zeebe/monitor/entity/VariableEntity.java b/src/main/java/io/zeebe/monitor/entity/VariableEntity.java index f8178d36..5f80822c 100644 --- a/src/main/java/io/zeebe/monitor/entity/VariableEntity.java +++ b/src/main/java/io/zeebe/monitor/entity/VariableEntity.java @@ -15,18 +15,25 @@ */ package io.zeebe.monitor.entity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Lob; +import javax.persistence.*; @Entity(name = "VARIABLE") +@Table(indexes = { + // performance reason, because we use it in the VariableRepository.findByProcessInstanceKey() + @Index(name = "variable_processInstanceKeyIndex", columnList = "PROCESS_INSTANCE_KEY_"), +}) public class VariableEntity { @Id + @Column(name = "ID") + private String id; + @Column(name = "POSITION_") private Long position; + @Column(name = "PARTITION_ID_") + private int partitionId; + @Column(name = "NAME_") private String name; @@ -46,6 +53,24 @@ public class VariableEntity { @Column(name = "TIMESTAMP_") private long timestamp; + public String getId() { + return id; + } + + private void setId(final String id) { + // made private, to avoid accidental changes + this.id = id; + } + + public final String getGeneratedIdentifier() { + return this.partitionId + "-" + this.position; + } + + @PrePersist + private void prePersistDeriveIdField(){ + setId(getGeneratedIdentifier()); + } + public String getState() { return state; } @@ -101,4 +126,12 @@ public Long getPosition() { public void setPosition(final Long position) { this.position = position; } + + public int getPartitionId() { + return partitionId; + } + + public void setPartitionId(final int partitionId) { + this.partitionId = partitionId; + } } diff --git a/src/main/java/io/zeebe/monitor/repository/ElementInstanceRepository.java b/src/main/java/io/zeebe/monitor/repository/ElementInstanceRepository.java index 2e00548a..6cd96cd7 100644 --- a/src/main/java/io/zeebe/monitor/repository/ElementInstanceRepository.java +++ b/src/main/java/io/zeebe/monitor/repository/ElementInstanceRepository.java @@ -18,7 +18,7 @@ import io.zeebe.monitor.entity.ElementInstanceEntity; import org.springframework.data.repository.CrudRepository; -public interface ElementInstanceRepository extends CrudRepository { +public interface ElementInstanceRepository extends CrudRepository { Iterable findByProcessInstanceKey(long processInstanceKey); } diff --git a/src/main/java/io/zeebe/monitor/repository/VariableRepository.java b/src/main/java/io/zeebe/monitor/repository/VariableRepository.java index 92137593..67d91d24 100644 --- a/src/main/java/io/zeebe/monitor/repository/VariableRepository.java +++ b/src/main/java/io/zeebe/monitor/repository/VariableRepository.java @@ -20,7 +20,7 @@ import java.util.List; -public interface VariableRepository extends PagingAndSortingRepository { +public interface VariableRepository extends PagingAndSortingRepository { List findByProcessInstanceKey(long processInstanceKey); } diff --git a/src/main/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporter.java b/src/main/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporter.java index 213c268b..5e0989f6 100644 --- a/src/main/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporter.java +++ b/src/main/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporter.java @@ -17,11 +17,15 @@ @Component public class ProcessAndElementImporter { - @Autowired private ProcessRepository processRepository; - @Autowired private ProcessInstanceRepository processInstanceRepository; - @Autowired private ElementInstanceRepository elementInstanceRepository; + @Autowired + private ProcessRepository processRepository; + @Autowired + private ProcessInstanceRepository processInstanceRepository; + @Autowired + private ElementInstanceRepository elementInstanceRepository; - @Autowired private ZeebeNotificationService notificationService; + @Autowired + private ZeebeNotificationService notificationService; public void importProcess(final Schema.ProcessRecord record) { final int partitionId = record.getMetadata().getPartitionId(); @@ -44,7 +48,6 @@ public void importProcessInstance(final Schema.ProcessInstanceRecord record) { if (record.getProcessInstanceKey() == record.getMetadata().getKey()) { addOrUpdateProcessInstance(record); } - addElementInstance(record); } @@ -97,13 +100,10 @@ private void addOrUpdateProcessInstance(final Schema.ProcessInstanceRecord recor } private void addElementInstance(final Schema.ProcessInstanceRecord record) { - - final long position = record.getMetadata().getPosition(); - if (!elementInstanceRepository.existsById(position)) { - - final ElementInstanceEntity entity = new ElementInstanceEntity(); - entity.setPosition(position); - entity.setPartitionId(record.getMetadata().getPartitionId()); + final ElementInstanceEntity entity = new ElementInstanceEntity(); + entity.setPartitionId(record.getMetadata().getPartitionId()); + entity.setPosition(record.getMetadata().getPosition()); + if (!elementInstanceRepository.existsById(entity.getGeneratedIdentifier())) { entity.setKey(record.getMetadata().getKey()); entity.setIntent(record.getMetadata().getIntent()); entity.setTimestamp(record.getMetadata().getTimestamp()); @@ -112,11 +112,8 @@ private void addElementInstance(final Schema.ProcessInstanceRecord record) { entity.setFlowScopeKey(record.getFlowScopeKey()); entity.setProcessDefinitionKey(record.getProcessDefinitionKey()); entity.setBpmnElementType(record.getBpmnElementType()); - elementInstanceRepository.save(entity); - - notificationService.sendProcessInstanceUpdated( - record.getProcessInstanceKey(), record.getProcessDefinitionKey()); + notificationService.sendProcessInstanceUpdated(record.getProcessInstanceKey(), record.getProcessDefinitionKey()); } } diff --git a/src/main/java/io/zeebe/monitor/zeebe/importers/VariableImporter.java b/src/main/java/io/zeebe/monitor/zeebe/importers/VariableImporter.java index e78ac055..731783f6 100644 --- a/src/main/java/io/zeebe/monitor/zeebe/importers/VariableImporter.java +++ b/src/main/java/io/zeebe/monitor/zeebe/importers/VariableImporter.java @@ -9,22 +9,21 @@ @Component public class VariableImporter { - @Autowired private VariableRepository variableRepository; + @Autowired + private VariableRepository variableRepository; public void importVariable(final Schema.VariableRecord record) { - - final long position = record.getMetadata().getPosition(); - if (!variableRepository.existsById(position)) { - - final VariableEntity entity = new VariableEntity(); - entity.setPosition(position); - entity.setTimestamp(record.getMetadata().getTimestamp()); - entity.setProcessInstanceKey(record.getProcessInstanceKey()); - entity.setName(record.getName()); - entity.setValue(record.getValue()); - entity.setScopeKey(record.getScopeKey()); - entity.setState(record.getMetadata().getIntent().toLowerCase()); - variableRepository.save(entity); + final VariableEntity newVariable = new VariableEntity(); + newVariable.setPosition(record.getMetadata().getPosition()); + newVariable.setPartitionId(record.getMetadata().getPartitionId()); + if (!variableRepository.existsById(newVariable.getGeneratedIdentifier())) { + newVariable.setTimestamp(record.getMetadata().getTimestamp()); + newVariable.setProcessInstanceKey(record.getProcessInstanceKey()); + newVariable.setName(record.getName()); + newVariable.setValue(record.getValue()); + newVariable.setScopeKey(record.getScopeKey()); + newVariable.setState(record.getMetadata().getIntent().toLowerCase()); + variableRepository.save(newVariable); } } diff --git a/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java b/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java new file mode 100644 index 00000000..46771241 --- /dev/null +++ b/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java @@ -0,0 +1,48 @@ +package io.zeebe.monitor.repository; + +import io.zeebe.monitor.entity.ElementInstanceEntity; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ElementInstanceRepositoryTest extends ZeebeRepositoryTest { + + @Autowired + private ElementInstanceRepository elementInstanceRepository; + + @Test + public void JPA_will_automatically_update_the_ID_attribute() { + // given + ElementInstanceEntity elementInstance = createElementInstance(); + + // when + elementInstanceRepository.save(elementInstance); + + // then + assertThat(elementInstance.getId()).isEqualTo("123-456"); + } + + @Test + public void variable_can_be_retrieved_by_transient_ID() { + // given + ElementInstanceEntity elementInstance = createElementInstance(); + + // when + elementInstanceRepository.save(elementInstance); + + // then + Optional entity = elementInstanceRepository.findById("123-456"); + assertThat(entity).isPresent(); + } + + private ElementInstanceEntity createElementInstance() { + ElementInstanceEntity elementInstance = new ElementInstanceEntity(); + elementInstance.setPartitionId(123); + elementInstance.setPosition(456L); + return elementInstance; + } + +} diff --git a/src/test/java/io/zeebe/monitor/repository/TestContextJpaConfiguration.java b/src/test/java/io/zeebe/monitor/repository/TestContextJpaConfiguration.java new file mode 100644 index 00000000..8020de67 --- /dev/null +++ b/src/test/java/io/zeebe/monitor/repository/TestContextJpaConfiguration.java @@ -0,0 +1,60 @@ +package io.zeebe.monitor.repository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableJpaRepositories(basePackages = "io.zeebe.monitor.repository") +@EnableTransactionManagement +public class TestContextJpaConfiguration { + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:mem:zeebe-monitor-test;DB_CLOSE_DELAY=-1"); + dataSource.setUsername("sa"); + dataSource.setPassword(""); + return dataSource; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Autowired DataSource dataSource) { + LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource); + em.setPackagesToScan("io.zeebe.monitor.entity"); + + JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(getAdditionalJpaProperties()); + + return em; + } + + @Bean + public PlatformTransactionManager transactionManager(@Autowired LocalContainerEntityManagerFactoryBean entityManagerFactory) { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory.getObject()); + return transactionManager; + } + + private Properties getAdditionalJpaProperties() { + Properties p = new Properties(); + p.setProperty("database-platform", "org.hibernate.dialect.H2Dialect"); + p.setProperty("hibernate.hbm2ddl.auto", "update"); + return p; + } + +} diff --git a/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java b/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java new file mode 100644 index 00000000..a4c75daa --- /dev/null +++ b/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java @@ -0,0 +1,48 @@ +package io.zeebe.monitor.repository; + +import io.zeebe.monitor.entity.VariableEntity; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +public class VariableRepositoryTest extends ZeebeRepositoryTest { + + @Autowired + private VariableRepository variableRepository; + + @Test + public void JPA_will_automatically_update_the_ID_attribute() { + // given + VariableEntity variable = createVariable(); + + // when + variableRepository.save(variable); + + // then + assertThat(variable.getId()).isEqualTo("123-456"); + } + + @Test + public void variable_can_be_retrieved_by_transient_ID() { + // given + VariableEntity variable = createVariable(); + + // when + variableRepository.save(variable); + + // then + Optional entity = variableRepository.findById("123-456"); + assertThat(entity).isPresent(); + } + + private VariableEntity createVariable() { + VariableEntity variable = new VariableEntity(); + variable.setPartitionId(123); + variable.setPosition(456L); + return variable; + } + +} diff --git a/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java b/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java new file mode 100644 index 00000000..99ff272c --- /dev/null +++ b/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java @@ -0,0 +1,18 @@ +package io.zeebe.monitor.repository; + +import org.junit.runner.RunWith; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration( + classes = {TestContextJpaConfiguration.class}, + loader = AnnotationConfigContextLoader.class) +@Transactional +@ActiveProfiles("junittest") +public abstract class ZeebeRepositoryTest { + // all Repository Tests should inherit from this one... +} diff --git a/src/test/java/io/zeebe/monitor/rest/ViewControllerTest.java b/src/test/java/io/zeebe/monitor/rest/ViewControllerTest.java index 41a03770..98c86df9 100644 --- a/src/test/java/io/zeebe/monitor/rest/ViewControllerTest.java +++ b/src/test/java/io/zeebe/monitor/rest/ViewControllerTest.java @@ -22,6 +22,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; import java.nio.file.Files; @@ -41,8 +42,10 @@ "white-label.custom.title: Test Zeebe Simple Monitor", "white-label.custom.css.path: css/test-custom.css", "white-label.custom.js.path: js/test-custom.js", + "logging.level.io.zeebe.monitor: info", }) @AutoConfigureMockMvc +@ActiveProfiles("junittest") public class ViewControllerTest { @Autowired diff --git a/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java b/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java new file mode 100644 index 00000000..54cd2bdc --- /dev/null +++ b/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java @@ -0,0 +1,56 @@ +package io.zeebe.monitor.zeebe.importers; + +import io.camunda.zeebe.protocol.record.intent.ProcessInstanceIntent; +import io.zeebe.exporter.proto.Schema; +import io.zeebe.monitor.entity.ElementInstanceEntity; +import io.zeebe.monitor.repository.ElementInstanceRepository; +import io.zeebe.monitor.repository.ZeebeRepositoryTest; +import io.zeebe.monitor.zeebe.ZeebeNotificationService; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.test.context.ContextConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +@ContextConfiguration( + classes = {ProcessAndElementImporter.class, + ZeebeNotificationService.class} +) +public class ProcessAndElementImporterTest extends ZeebeRepositoryTest { + + @Autowired + ProcessAndElementImporter processAndElementImporter; + + @Autowired + ElementInstanceRepository elementInstanceRepository; + + @MockBean + SimpMessagingTemplate simpMessagingTemplate; + + @Test + public void only_storing_first_variable_event_prevents_duplicate_PartitionID_and_Position() { + // given + Schema.ProcessInstanceRecord processInstance1 = createElementInstanceWithId("first-elementId"); + processAndElementImporter.importProcessInstance(processInstance1); + + // when + Schema.ProcessInstanceRecord processInstance2 = createElementInstanceWithId("second-elementId"); + processAndElementImporter.importProcessInstance(processInstance2); + + // then + Iterable all = elementInstanceRepository.findAll(); + assertThat(all).hasSize(1); + assertThat(all.iterator().next().getElementId()).isEqualTo("first-elementId"); + } + + private Schema.ProcessInstanceRecord createElementInstanceWithId(String elementId) { + return Schema.ProcessInstanceRecord.newBuilder() + .setElementId(elementId) + .setMetadata(Schema.RecordMetadata.newBuilder() + .setIntent(ProcessInstanceIntent.ELEMENT_ACTIVATED.name())) + .build(); + } + +} diff --git a/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java b/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java new file mode 100644 index 00000000..360ed72f --- /dev/null +++ b/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java @@ -0,0 +1,48 @@ +package io.zeebe.monitor.zeebe.importers; + +import io.zeebe.exporter.proto.Schema; +import io.zeebe.monitor.entity.VariableEntity; +import io.zeebe.monitor.repository.VariableRepository; +import io.zeebe.monitor.repository.ZeebeRepositoryTest; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +@ContextConfiguration( + classes = {VariableImporter.class} +) +public class VariableImporterTest extends ZeebeRepositoryTest { + + @Autowired + VariableImporter variableImporter; + + @Autowired + VariableRepository variableRepository; + + @Test + public void only_storing_first_variable_event_prevents_duplicate_PartitionID_and_Position() { + // given + Schema.VariableRecord record1 = createVariableRecordWithName("first-variable"); + variableImporter.importVariable(record1); + + // when + Schema.VariableRecord record2 = createVariableRecordWithName("second-variable"); + variableImporter.importVariable(record2); + + // then + Iterable all = variableRepository.findAll(); + assertThat(all).hasSize(1); + assertThat(all.iterator().next().getName()).isEqualTo("first-variable"); + } + + private Schema.VariableRecord createVariableRecordWithName(String name) { + return Schema.VariableRecord.newBuilder() + .setMetadata(Schema.RecordMetadata.newBuilder() + .setPartitionId(123) + .setPosition(456L)) + .setName(name) + .build(); + } +} diff --git a/src/test/resources/application-junittest.yaml b/src/test/resources/application-junittest.yaml new file mode 100644 index 00000000..14a1f5a5 --- /dev/null +++ b/src/test/resources/application-junittest.yaml @@ -0,0 +1,4 @@ +logging: + level: + root: WARN + io.zeebe: INFO From f38ceda044add8a01bc9cc1a198590fda49e94e2 Mon Sep 17 00:00:00 2001 From: nitram509 Date: Fri, 27 Aug 2021 23:32:48 +0200 Subject: [PATCH 2/2] rework from JUnit4.x to JUnit5.x add partitionId and position as recommended, https://github.com/camunda-community-hub/zeebe-simple-monitor/pull/285#pullrequestreview-740435360 --- .../monitor/repository/ElementInstanceRepositoryTest.java | 2 +- .../io/zeebe/monitor/repository/VariableRepositoryTest.java | 2 +- .../io/zeebe/monitor/repository/ZeebeRepositoryTest.java | 5 ++--- .../zeebe/importers/ProcessAndElementImporterTest.java | 4 +++- .../zeebe/monitor/zeebe/importers/VariableImporterTest.java | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java b/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java index 46771241..f24e30e9 100644 --- a/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java +++ b/src/test/java/io/zeebe/monitor/repository/ElementInstanceRepositoryTest.java @@ -1,7 +1,7 @@ package io.zeebe.monitor.repository; import io.zeebe.monitor.entity.ElementInstanceEntity; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.Optional; diff --git a/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java b/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java index a4c75daa..c6999ef8 100644 --- a/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java +++ b/src/test/java/io/zeebe/monitor/repository/VariableRepositoryTest.java @@ -1,7 +1,7 @@ package io.zeebe.monitor.repository; import io.zeebe.monitor.entity.VariableEntity; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.Optional; diff --git a/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java b/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java index 99ff272c..e7538c16 100644 --- a/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java +++ b/src/test/java/io/zeebe/monitor/repository/ZeebeRepositoryTest.java @@ -1,13 +1,12 @@ package io.zeebe.monitor.repository; -import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; import org.springframework.transaction.annotation.Transactional; -@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest @ContextConfiguration( classes = {TestContextJpaConfiguration.class}, loader = AnnotationConfigContextLoader.class) diff --git a/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java b/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java index 54cd2bdc..43bf111c 100644 --- a/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java +++ b/src/test/java/io/zeebe/monitor/zeebe/importers/ProcessAndElementImporterTest.java @@ -6,7 +6,7 @@ import io.zeebe.monitor.repository.ElementInstanceRepository; import io.zeebe.monitor.repository.ZeebeRepositoryTest; import io.zeebe.monitor.zeebe.ZeebeNotificationService; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.messaging.simp.SimpMessagingTemplate; @@ -49,6 +49,8 @@ private Schema.ProcessInstanceRecord createElementInstanceWithId(String elementI return Schema.ProcessInstanceRecord.newBuilder() .setElementId(elementId) .setMetadata(Schema.RecordMetadata.newBuilder() + .setPosition(333L) + .setPartitionId(55555) .setIntent(ProcessInstanceIntent.ELEMENT_ACTIVATED.name())) .build(); } diff --git a/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java b/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java index 360ed72f..91e71780 100644 --- a/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java +++ b/src/test/java/io/zeebe/monitor/zeebe/importers/VariableImporterTest.java @@ -4,7 +4,7 @@ import io.zeebe.monitor.entity.VariableEntity; import io.zeebe.monitor.repository.VariableRepository; import io.zeebe.monitor.repository.ZeebeRepositoryTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration;