From 8f1fff61dfd55fc5e757f61e968f14f79da15363 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Fri, 21 Mar 2025 16:31:30 +0200 Subject: [PATCH 1/4] Fix equals method for CF --- .../cf/DefaultCalculatedFieldCache.java | 3 + .../DefaultEntitiesExportImportService.java | 2 - .../service/sync/vc/VersionControlTest.java | 2 + .../common/data/cf/CalculatedField.java | 57 ++++++++++++++----- .../ScriptCalculatedFieldConfiguration.java | 3 + .../SimpleCalculatedFieldConfiguration.java | 2 + 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java b/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java index 64487d9b3e..219a261183 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/DefaultCalculatedFieldCache.java @@ -144,6 +144,9 @@ public class DefaultCalculatedFieldCache implements CalculatedFieldCache { calculatedFieldFetchLock.lock(); try { CalculatedField calculatedField = calculatedFieldService.findById(tenantId, calculatedFieldId); + if (calculatedField == null) { + return; + } EntityId cfEntityId = calculatedField.getEntityId(); calculatedFields.put(calculatedFieldId, calculatedField); diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java index 06fe7f4036..db7e37b368 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/DefaultEntitiesExportImportService.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.sync.ie.EntityExportData; import org.thingsboard.server.common.data.sync.ie.EntityImportResult; import org.thingsboard.server.common.data.util.ThrowingRunnable; -import org.thingsboard.server.dao.cf.CalculatedFieldService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -62,7 +61,6 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS private final Map> importServices = new HashMap<>(); private final RelationService relationService; - private final CalculatedFieldService calculatedFieldService; private final RateLimitService rateLimitService; private final TbLogEntityActionService logEntityActionService; diff --git a/application/src/test/java/org/thingsboard/server/service/sync/vc/VersionControlTest.java b/application/src/test/java/org/thingsboard/server/service/sync/vc/VersionControlTest.java index 06f61ca4e5..29c3af5387 100644 --- a/application/src/test/java/org/thingsboard/server/service/sync/vc/VersionControlTest.java +++ b/application/src/test/java/org/thingsboard/server/service/sync/vc/VersionControlTest.java @@ -621,6 +621,7 @@ public class VersionControlTest extends AbstractControllerTest { assertThat(importedField.getName()).isEqualTo(deviceCalculatedField.getName()); assertThat(importedField.getType()).isEqualTo(deviceCalculatedField.getType()); assertThat(importedField.getId()).isNotEqualTo(deviceCalculatedField.getId()); + assertThat(importedField.getConfiguration().getArguments().get("T").getRefEntityId()).isEqualTo(importedAsset.getId()); }); List importedAssetCalculatedFields = findCalculatedFieldsByEntityId(importedAsset.getId()); @@ -629,6 +630,7 @@ public class VersionControlTest extends AbstractControllerTest { assertThat(importedField.getName()).isEqualTo(assetCalculatedField.getName()); assertThat(importedField.getType()).isEqualTo(assetCalculatedField.getType()); assertThat(importedField.getId()).isNotEqualTo(assetCalculatedField.getId()); + assertThat(importedField.getConfiguration().getArguments().get("T").getRefEntityId()).isEqualTo(importedDevice.getId()); }); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java index b86f30ca78..ea7f81f216 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonSetter; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import org.thingsboard.server.common.data.BaseData; @@ -37,10 +36,10 @@ import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; import java.io.Serial; +import java.util.Objects; @Schema @Data -@EqualsAndHashCode(callSuper = true) public class CalculatedField extends BaseData implements HasName, HasTenantId, HasVersion, HasDebugSettings { @Serial @@ -112,6 +111,48 @@ public class CalculatedField extends BaseData implements HasN return super.getCreatedTime(); } + // Getter is ignored for serialization + @JsonIgnore + public boolean isDebugMode() { + return debugMode; + } + + // Setter is annotated for deserialization + @JsonSetter + public void setDebugMode(boolean debugMode) { + this.debugMode = debugMode; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CalculatedField that)) return false; + if (!super.equals(o)) return false; + return Objects.equals(tenantId, that.tenantId) && + Objects.equals(entityId, that.entityId) && + Objects.equals(name, that.name) && + Objects.equals(debugSettings, that.debugSettings) && + Objects.equals(configuration, that.configuration) && + type == that.type && debugMode == that.debugMode && + configurationVersion == that.configurationVersion && + Objects.equals(version, that.version); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + Objects.hashCode(tenantId); + result = 31 * result + Objects.hashCode(entityId); + result = 31 * result + Objects.hashCode(type); + result = 31 * result + Objects.hashCode(name); + result = 31 * result + Boolean.hashCode(debugMode); + result = 31 * result + Objects.hashCode(debugSettings); + result = 31 * result + Integer.hashCode(configurationVersion); + result = 31 * result + Objects.hashCode(configuration); + result = 31 * result + Objects.hashCode(version); + return result; + } + @Override public String toString() { return new StringBuilder() @@ -128,16 +169,4 @@ public class CalculatedField extends BaseData implements HasN .toString(); } - // Getter is ignored for serialization - @JsonIgnore - public boolean isDebugMode() { - return debugMode; - } - - // Setter is annotated for deserialization - @JsonSetter - public void setDebugMode(boolean debugMode) { - this.debugMode = debugMode; - } - } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScriptCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScriptCalculatedFieldConfiguration.java index 0971217fdf..c2dde43b8e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScriptCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/ScriptCalculatedFieldConfiguration.java @@ -16,13 +16,16 @@ package org.thingsboard.server.common.data.cf.configuration; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.cf.CalculatedFieldType; @Data +@EqualsAndHashCode(callSuper = true) public class ScriptCalculatedFieldConfiguration extends BaseCalculatedFieldConfiguration implements CalculatedFieldConfiguration { @Override public CalculatedFieldType getType() { return CalculatedFieldType.SCRIPT; } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java index 79a0518ba0..0a422de175 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java @@ -16,9 +16,11 @@ package org.thingsboard.server.common.data.cf.configuration; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.cf.CalculatedFieldType; @Data +@EqualsAndHashCode(callSuper = true) public class SimpleCalculatedFieldConfiguration extends BaseCalculatedFieldConfiguration implements CalculatedFieldConfiguration { @Override From 77721d5684968e9e72c487a72659423106e1e57d Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 24 Mar 2025 09:49:40 +0200 Subject: [PATCH 2/4] Fix CFControllerTest --- .../server/controller/CalculatedFieldControllerTest.java | 9 ++++----- .../SimpleCalculatedFieldConfiguration.java | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java index ee66f664cc..af43b34558 100644 --- a/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/CalculatedFieldControllerTest.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.cf.configuration.OutputType; import org.thingsboard.server.common.data.cf.configuration.ReferencedEntityKey; import org.thingsboard.server.common.data.cf.configuration.SimpleCalculatedFieldConfiguration; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.service.DaoSqlTest; @@ -85,7 +84,7 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest { assertThat(savedCalculatedField.getEntityId()).isEqualTo(calculatedField.getEntityId()); assertThat(savedCalculatedField.getType()).isEqualTo(calculatedField.getType()); assertThat(savedCalculatedField.getName()).isEqualTo(calculatedField.getName()); - assertThat(savedCalculatedField.getConfiguration()).isEqualTo(getCalculatedFieldConfig(testDevice.getId())); + assertThat(savedCalculatedField.getConfiguration()).isEqualTo(getCalculatedFieldConfig()); assertThat(savedCalculatedField.getVersion()).isEqualTo(1L); savedCalculatedField.setName("Test CF"); @@ -134,16 +133,16 @@ public class CalculatedFieldControllerTest extends AbstractControllerTest { calculatedField.setType(CalculatedFieldType.SIMPLE); calculatedField.setName("Test Calculated Field"); calculatedField.setConfigurationVersion(1); - calculatedField.setConfiguration(getCalculatedFieldConfig(null)); + calculatedField.setConfiguration(getCalculatedFieldConfig()); calculatedField.setVersion(1L); return calculatedField; } - private CalculatedFieldConfiguration getCalculatedFieldConfig(EntityId referencedEntityId) { + private CalculatedFieldConfiguration getCalculatedFieldConfig() { SimpleCalculatedFieldConfiguration config = new SimpleCalculatedFieldConfiguration(); Argument argument = new Argument(); - argument.setRefEntityId(referencedEntityId); + argument.setRefEntityId(null); ReferencedEntityKey refEntityKey = new ReferencedEntityKey("temperature", ArgumentType.TS_LATEST, null); argument.setRefEntityKey(refEntityKey); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java index 0a422de175..5c0ce71e86 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/configuration/SimpleCalculatedFieldConfiguration.java @@ -27,4 +27,5 @@ public class SimpleCalculatedFieldConfiguration extends BaseCalculatedFieldConfi public CalculatedFieldType getType() { return CalculatedFieldType.SIMPLE; } + } From 3f089da378ec5debdf44d3f777222aac56415f5e Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 24 Mar 2025 11:57:46 +0200 Subject: [PATCH 3/4] Fix tbCalculatedFieldNotificationsTopic --- .../org/thingsboard/server/queue/discovery/TopicService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java index 5992083d85..cfd796e361 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TopicService.java @@ -47,7 +47,7 @@ public class TopicService { @Value("${queue.edge.event-notifications-topic:tb_edge_event.notifications}") private String tbEdgeEventNotificationsTopic; - @Value("${queue.calculated_fields.notifications-topic:calculated_field.notifications}") + @Value("${queue.calculated-fields.notifications-topic:calculated_field.notifications}") private String tbCalculatedFieldNotificationsTopic; private final ConcurrentMap tbCoreNotificationTopics = new ConcurrentHashMap<>(); From 27352b7b7e977911604941986ea2c93e8be60bac Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Fri, 4 Apr 2025 09:19:17 +0300 Subject: [PATCH 4/4] Improve after review --- .../common/data/cf/CalculatedField.java | 35 ++----------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java b/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java index ea7f81f216..3b2ddf0627 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/cf/CalculatedField.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonSetter; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import org.thingsboard.server.common.data.BaseData; @@ -36,10 +37,10 @@ import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; import java.io.Serial; -import java.util.Objects; @Schema @Data +@EqualsAndHashCode(callSuper = true) public class CalculatedField extends BaseData implements HasName, HasTenantId, HasVersion, HasDebugSettings { @Serial @@ -63,7 +64,7 @@ public class CalculatedField extends BaseData implements HasN @Schema(description = "Version of calculated field configuration.", example = "0") private int configurationVersion; @Schema(implementation = SimpleCalculatedFieldConfiguration.class) - private transient CalculatedFieldConfiguration configuration; + private CalculatedFieldConfiguration configuration; @Getter @Setter private Long version; @@ -123,36 +124,6 @@ public class CalculatedField extends BaseData implements HasN this.debugMode = debugMode; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof CalculatedField that)) return false; - if (!super.equals(o)) return false; - return Objects.equals(tenantId, that.tenantId) && - Objects.equals(entityId, that.entityId) && - Objects.equals(name, that.name) && - Objects.equals(debugSettings, that.debugSettings) && - Objects.equals(configuration, that.configuration) && - type == that.type && debugMode == that.debugMode && - configurationVersion == that.configurationVersion && - Objects.equals(version, that.version); - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = 31 * result + Objects.hashCode(tenantId); - result = 31 * result + Objects.hashCode(entityId); - result = 31 * result + Objects.hashCode(type); - result = 31 * result + Objects.hashCode(name); - result = 31 * result + Boolean.hashCode(debugMode); - result = 31 * result + Objects.hashCode(debugSettings); - result = 31 * result + Integer.hashCode(configurationVersion); - result = 31 * result + Objects.hashCode(configuration); - result = 31 * result + Objects.hashCode(version); - return result; - } - @Override public String toString() { return new StringBuilder()