From 924c9cf5d038084fda404185c8e7a60b3cd508f6 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Wed, 21 Jan 2026 09:19:47 +0100 Subject: [PATCH 1/2] hotfix count query by tenant on cf_manager init --- .../device/DefaultNativeAssetRepository.java | 25 ++++++++++--------- .../device/DefaultNativeDeviceRepository.java | 24 +++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java index 3a11f70a94..e7ba0c206c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeAssetRepository.java @@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; +import java.util.Map; import java.util.UUID; @Repository @@ -41,22 +42,22 @@ public class DefaultNativeAssetRepository extends AbstractNativeRepository imple @Override public PageData findProfileEntityIdInfos(Pageable pageable) { String PROFILE_ASSET_ID_INFO_QUERY = "SELECT tenant_id as tenantId, asset_profile_id as profileId, id as id FROM asset ORDER BY created_time ASC LIMIT %s OFFSET %s"; - return find(COUNT_QUERY, PROFILE_ASSET_ID_INFO_QUERY, pageable, row -> { - AssetId id = new AssetId((UUID) row.get("id")); - AssetProfileId profileId = new AssetProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + return find(COUNT_QUERY, PROFILE_ASSET_ID_INFO_QUERY, pageable, DefaultNativeAssetRepository::toInfo); } @Override public PageData findProfileEntityIdInfosByTenantId(UUID tenantId, Pageable pageable) { String PROFILE_ASSET_ID_INFO_QUERY = String.format("SELECT tenant_id as tenantId, asset_profile_id as profileId, id as id FROM asset WHERE tenant_id = '%s' ORDER BY created_time ASC LIMIT %%s OFFSET %%s", tenantId); - return find(COUNT_QUERY, PROFILE_ASSET_ID_INFO_QUERY, pageable, row -> { - AssetId id = new AssetId((UUID) row.get("id")); - AssetProfileId profileId = new AssetProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + String COUNT_QUERY_BY_TENANT = String.format("SELECT count(id) FROM asset WHERE tenant_id = '%s';", tenantId); + return find(COUNT_QUERY_BY_TENANT, PROFILE_ASSET_ID_INFO_QUERY, pageable, DefaultNativeAssetRepository::toInfo); } + + private static ProfileEntityIdInfo toInfo(Map row) { + var tenantIdObj = row.get("tenantId"); + UUID tenantId = tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(); + AssetId id = new AssetId((UUID) row.get("id")); + AssetProfileId profileId = new AssetProfileId((UUID) row.get("profileId")); + return ProfileEntityIdInfo.create(tenantId, profileId, id); + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java index b039f30d32..c4ba36ce2e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DefaultNativeDeviceRepository.java @@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; +import java.util.Map; import java.util.UUID; @Repository @@ -53,23 +54,22 @@ public class DefaultNativeDeviceRepository extends AbstractNativeRepository impl @Override public PageData findProfileEntityIdInfos(Pageable pageable) { String PROFILE_DEVICE_ID_INFO_QUERY = "SELECT tenant_id as tenantId, device_profile_id as profileId, id as id FROM device ORDER BY created_time ASC LIMIT %s OFFSET %s"; - return find(COUNT_QUERY, PROFILE_DEVICE_ID_INFO_QUERY, pageable, row -> { - DeviceId id = new DeviceId((UUID) row.get("id")); - DeviceProfileId profileId = new DeviceProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + return find(COUNT_QUERY, PROFILE_DEVICE_ID_INFO_QUERY, pageable, DefaultNativeDeviceRepository::toInfo); } @Override public PageData findProfileEntityIdInfosByTenantId(UUID tenantId, Pageable pageable) { String PROFILE_DEVICE_ID_INFO_QUERY = String.format("SELECT tenant_id as tenantId, device_profile_id as profileId, id as id FROM device WHERE tenant_id = '%s' ORDER BY created_time ASC LIMIT %%s OFFSET %%s", tenantId); - return find(COUNT_QUERY, PROFILE_DEVICE_ID_INFO_QUERY, pageable, row -> { - DeviceId id = new DeviceId((UUID) row.get("id")); - DeviceProfileId profileId = new DeviceProfileId((UUID) row.get("profileId")); - var tenantIdObj = row.get("tenantId"); - return ProfileEntityIdInfo.create(tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(), profileId, id); - }); + String COUNT_QUERY_BY_TENANT = String.format("SELECT count(id) FROM device WHERE tenant_id = '%s';", tenantId); + return find(COUNT_QUERY_BY_TENANT, PROFILE_DEVICE_ID_INFO_QUERY, pageable, DefaultNativeDeviceRepository::toInfo); + } + + private static ProfileEntityIdInfo toInfo(Map row) { + var tenantIdObj = row.get("tenantId"); + UUID tenantId = tenantIdObj != null ? (UUID) tenantIdObj : TenantId.SYS_TENANT_ID.getId(); + DeviceId id = new DeviceId((UUID) row.get("id")); + DeviceProfileId profileId = new DeviceProfileId((UUID) row.get("profileId")); + return ProfileEntityIdInfo.create(tenantId, profileId, id); } } From 73fa6734c4925708d4632f7bcf4f7d9145bf15fa Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Thu, 22 Jan 2026 09:54:11 +0200 Subject: [PATCH 2/2] updated error message on cf init --- .../CalculatedFieldManagerMessageProcessor.java | 6 +++--- .../server/service/cf/ctx/state/CalculatedFieldCtx.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java index fed1cc3ada..65ec0b332b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/calculatedField/CalculatedFieldManagerMessageProcessor.java @@ -262,7 +262,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware try { cfCtx.init(); } catch (Exception e) { - throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage("Failed to initialize CF context").build(); + throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage(e.getMessage()).build(); } calculatedFields.put(cf.getId(), cfCtx); // We use copy on write lists to safely pass the reference to another actor for the iteration. @@ -289,7 +289,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware try { newCfCtx.init(); } catch (Exception e) { - throw CalculatedFieldException.builder().ctx(newCfCtx).eventEntity(newCfCtx.getEntityId()).cause(e).errorMessage("Failed to initialize CF context").build(); + throw CalculatedFieldException.builder().ctx(newCfCtx).eventEntity(newCfCtx.getEntityId()).cause(e).errorMessage(e.getMessage()).build(); } finally { calculatedFields.put(newCf.getId(), newCfCtx); List oldCfList = entityIdCalculatedFields.get(newCf.getEntityId()); @@ -552,7 +552,7 @@ public class CalculatedFieldManagerMessageProcessor extends AbstractContextAware try { cfCtx.init(); } catch (Exception e) { - throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage("Failed to initialize CF context").build(); + throw CalculatedFieldException.builder().ctx(cfCtx).eventEntity(cf.getEntityId()).cause(e).errorMessage(e.getMessage()).build(); } finally { calculatedFields.put(cf.getId(), cfCtx); // We use copy on write lists to safely pass the reference to another actor for the iteration. diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java index 3438760778..5d0ff5c2ff 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/CalculatedFieldCtx.java @@ -114,7 +114,7 @@ public class CalculatedFieldCtx { initialized = true; } catch (Exception e) { initialized = false; - throw new RuntimeException("Failed to init calculated field ctx. Invalid expression syntax.", e); + throw new RuntimeException("Failed to initialize CF context. The script expression is invalid. Please check for syntax errors or unsupported functions.", e); } } else { if (isValidExpression(expression)) { @@ -128,7 +128,7 @@ public class CalculatedFieldCtx { initialized = true; } else { initialized = false; - throw new RuntimeException("Failed to init calculated field ctx. Invalid expression syntax."); + throw new RuntimeException("Failed to initialize CF context. The expression has invalid syntax or unknown variables. Ensure all mathematical operators are correct."); } } }