From 30330057dbc64801b41e02e0a93e0cfa4fb420d1 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 11:01:51 +0200 Subject: [PATCH 01/59] Replaced deprecated @MockBean/@SpyBean with @MockitoBean in dao tests Spring Boot 3.4 deprecated @MockBean/@SpyBean in favor of @MockitoBean/@MockitoSpyBean. The 'answer' attribute was renamed to 'answers'. --- .../server/dao/AbstractDaoServiceTest.java | 4 ++-- .../server/dao/AbstractJpaDaoTest.java | 4 ++-- .../cache/RedisTbTransactionalCacheTest.java | 10 +++++----- .../server/dao/service/DeviceServiceTest.java | 4 ++-- .../server/dao/service/TenantServiceTest.java | 4 ++-- .../AdminSettingsDataValidatorTest.java | 8 ++++---- .../validator/AlarmDataValidatorTest.java | 8 ++++---- .../validator/AssetDataValidatorTest.java | 8 ++++---- .../AssetProfileDataValidatorTest.java | 18 ++++++++--------- .../CalculatedFieldDataValidatorTest.java | 10 +++++----- .../CalculatedFieldLinkDataValidatorTest.java | 8 ++++---- .../ComponentDescriptorDataValidatorTest.java | 4 ++-- .../validator/CustomerDataValidatorTest.java | 10 +++++----- .../validator/DashboardDataValidatorTest.java | 8 ++++---- .../validator/DeviceDataValidatorTest.java | 8 ++++---- .../DeviceProfileDataValidatorTest.java | 20 +++++++++---------- .../validator/EdgeDataValidatorTest.java | 12 +++++------ .../EntityViewDataValidatorTest.java | 12 +++++------ .../validator/ResourceDataValidatorTest.java | 14 ++++++------- .../validator/RuleChainDataValidatorTest.java | 10 +++++----- .../validator/TenantDataValidatorTest.java | 8 ++++---- .../TenantProfileDataValidatorTest.java | 10 +++++----- .../WidgetTypeDataValidatorTest.java | 12 +++++------ .../WidgetsBundleDataValidatorTest.java | 10 +++++----- .../DefaultEntityQueryRepositoryTest.java | 8 ++++---- .../query/DefaultQueryLogComponentTest.java | 4 ++-- ...esDaoPartitioningDaysAlwaysExistsTest.java | 8 ++++---- ...sDaoPartitioningHoursAlwaysExistsTest.java | 8 ++++---- ...artitioningIndefiniteAlwaysExistsTest.java | 8 ++++---- ...aoPartitioningMinutesAlwaysExistsTest.java | 8 ++++---- ...DaoPartitioningMonthsAlwaysExistsTest.java | 8 ++++---- ...sDaoPartitioningYearsAlwaysExistsTest.java | 8 ++++---- 32 files changed, 142 insertions(+), 142 deletions(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java index 267dd52882..4aa50de3cc 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractDaoServiceTest.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao; import org.junit.runner.RunWith; import org.mockito.Answers; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; @@ -40,7 +40,7 @@ import org.thingsboard.server.dao.service.DaoSqlTest; DirtiesContextTestExecutionListener.class}) public abstract class AbstractDaoServiceTest { - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) StatsFactory statsFactory; } diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java index f68ab72786..dc5cc47cf7 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao; import org.junit.runner.RunWith; import org.mockito.Answers; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringRunner; @@ -42,7 +42,7 @@ import org.thingsboard.server.dao.service.DaoSqlTest; DirtiesContextTestExecutionListener.class}) public abstract class AbstractJpaDaoTest { - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) StatsFactory statsFactory; } diff --git a/dao/src/test/java/org/thingsboard/server/dao/cache/RedisTbTransactionalCacheTest.java b/dao/src/test/java/org/thingsboard/server/dao/cache/RedisTbTransactionalCacheTest.java index 5de4378cf0..a9feec982b 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/cache/RedisTbTransactionalCacheTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/cache/RedisTbTransactionalCacheTest.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.cache; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.test.context.ContextConfiguration; @@ -50,13 +50,13 @@ import static org.mockito.Mockito.when; @Slf4j public class RedisTbTransactionalCacheTest { - @MockBean + @MockitoBean private RelationRedisCache relationRedisCache; - @MockBean + @MockitoBean private RedisConnectionFactory connectionFactory; - @MockBean + @MockitoBean private RedisConnection redisConnection; - @MockBean + @MockitoBean private RedisSslCredentials redisSslCredentials; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/DeviceServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/DeviceServiceTest.java index 94745c804e..90e3bf0603 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/DeviceServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/DeviceServiceTest.java @@ -23,7 +23,7 @@ import org.junit.Test; import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -103,7 +103,7 @@ public class DeviceServiceTest extends AbstractServiceTest { private CalculatedFieldService calculatedFieldService; @Autowired private PlatformTransactionManager platformTransactionManager; - @SpyBean + @MockitoSpyBean private DeviceCredentialsDataValidator validator; private IdComparator idComparator = new IdComparator<>(); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/TenantServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/TenantServiceTest.java index e9f5b4d16f..45b39c3ad7 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/TenantServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/TenantServiceTest.java @@ -20,7 +20,7 @@ import org.junit.Test; import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.cache.TbTransactionalCache; import org.thingsboard.server.common.data.Customer; @@ -87,7 +87,7 @@ import static org.mockito.Mockito.verify; @DaoSqlTest public class TenantServiceTest extends AbstractServiceTest { - @SpyBean + @MockitoSpyBean TenantDao tenantDao; @Autowired diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidatorTest.java index c550772718..6241f2dea3 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AdminSettingsDataValidatorTest.java @@ -17,8 +17,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.id.TenantId; @@ -31,9 +31,9 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = AdminSettingsDataValidator.class) class AdminSettingsDataValidatorTest { - @MockBean + @MockitoBean AdminSettingsService adminSettingsService; - @SpyBean + @MockitoSpyBean AdminSettingsDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AlarmDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AlarmDataValidatorTest.java index 89b0b0cec4..e36aa20773 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AlarmDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AlarmDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.id.TenantId; @@ -33,9 +33,9 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = AlarmDataValidator.class) class AlarmDataValidatorTest { - @MockBean + @MockitoBean TenantService tenantService; - @SpyBean + @MockitoSpyBean AlarmDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetDataValidatorTest.java index 540d25578a..730daff5c5 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetDataValidatorTest.java @@ -22,7 +22,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.asset.AssetDao; @@ -39,11 +39,11 @@ import static org.mockito.BDDMockito.willReturn; @Slf4j class AssetDataValidatorTest { - @MockBean + @MockitoBean AssetDao assetDao; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean CustomerDao customerDao; @Autowired AssetDataValidator validator; diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetProfileDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetProfileDataValidatorTest.java index b5cfb4998c..a8060cd51f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetProfileDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/AssetProfileDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.asset.AssetProfile; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.asset.AssetProfileDao; @@ -37,19 +37,19 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = AssetProfileDataValidator.class) class AssetProfileDataValidatorTest { - @MockBean + @MockitoBean AssetProfileDao assetProfileDao; - @MockBean + @MockitoBean AssetProfileService assetProfileService; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean QueueService queueService; - @MockBean + @MockitoBean RuleChainService ruleChainService; - @MockBean + @MockitoBean DashboardService dashboardService; - @SpyBean + @MockitoSpyBean AssetProfileDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldDataValidatorTest.java index 221782b23c..e781e60113 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldDataValidatorTest.java @@ -17,8 +17,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.cf.CalculatedField; import org.thingsboard.server.common.data.cf.CalculatedFieldType; import org.thingsboard.server.common.data.id.CalculatedFieldId; @@ -38,11 +38,11 @@ public class CalculatedFieldDataValidatorTest { private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("7b5229e9-166e-41a9-a257-3b1dafad1b04")); private final CalculatedFieldId CALCULATED_FIELD_ID = new CalculatedFieldId(UUID.fromString("060fbe45-fbb2-4549-abf3-f72a6be3cb9f")); - @MockBean + @MockitoBean private CalculatedFieldDao calculatedFieldDao; - @MockBean + @MockitoBean private DefaultApiLimitService apiLimitService; - @SpyBean + @MockitoSpyBean private CalculatedFieldDataValidator validator; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldLinkDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldLinkDataValidatorTest.java index 41d16a0670..9ba5133071 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldLinkDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/CalculatedFieldLinkDataValidatorTest.java @@ -17,8 +17,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.cf.CalculatedFieldLink; import org.thingsboard.server.common.data.id.CalculatedFieldId; import org.thingsboard.server.common.data.id.CalculatedFieldLinkId; @@ -37,9 +37,9 @@ public class CalculatedFieldLinkDataValidatorTest { private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("2ba09d99-6143-43dc-b645-381fc0c43ebe")); private final CalculatedFieldLinkId CALCULATED_FIELD_LINK_ID = new CalculatedFieldLinkId(UUID.fromString("a5609ef4-cb42-43ce-9b23-e090a4878d1c")); - @MockBean + @MockitoBean private CalculatedFieldLinkDao calculatedFieldLinkDao; - @SpyBean + @MockitoSpyBean private CalculatedFieldLinkDataValidator validator; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidatorTest.java index c810dd5c63..1dfc1d4e8d 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/ComponentDescriptorDataValidatorTest.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentScope; @@ -27,7 +27,7 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = ComponentDescriptorDataValidator.class) class ComponentDescriptorDataValidatorTest { - @SpyBean + @MockitoSpyBean ComponentDescriptorDataValidator validator; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/CustomerDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/CustomerDataValidatorTest.java index d434d8f231..aa66f4003f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/CustomerDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/CustomerDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.customer.CustomerDao; @@ -33,11 +33,11 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = CustomerDataValidator.class) class CustomerDataValidatorTest { - @MockBean + @MockitoBean CustomerDao customerDao; - @MockBean + @MockitoBean TenantService tenantService; - @SpyBean + @MockitoSpyBean CustomerDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/DashboardDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/DashboardDataValidatorTest.java index 3029027f37..cf5ad6e8fe 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/DashboardDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/DashboardDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.tenant.TenantService; @@ -32,9 +32,9 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = DashboardDataValidator.class) class DashboardDataValidatorTest { - @MockBean + @MockitoBean TenantService tenantService; - @SpyBean + @MockitoSpyBean DashboardDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceDataValidatorTest.java index 260114abd7..ae55b2caa5 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceDataValidatorTest.java @@ -22,7 +22,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.customer.CustomerDao; @@ -39,11 +39,11 @@ import static org.mockito.BDDMockito.willReturn; @Slf4j class DeviceDataValidatorTest { - @MockBean + @MockitoBean DeviceDao deviceDao; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean CustomerDao customerDao; @Autowired DeviceDataValidator validator; diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidatorTest.java index f3f172a5ce..b9a532f7d1 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileType; @@ -83,21 +83,21 @@ class DeviceProfileDataValidatorTest { private static final int port = 5685; private static final int portBs = 5687; - @MockBean + @MockitoBean DeviceProfileDao deviceProfileDao; - @MockBean + @MockitoBean DeviceProfileService deviceProfileService; - @MockBean + @MockitoBean DeviceDao deviceDao; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean QueueService queueService; - @MockBean + @MockitoBean RuleChainService ruleChainService; - @MockBean + @MockitoBean DashboardService dashboardService; - @SpyBean + @MockitoSpyBean DeviceProfileDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/EdgeDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/EdgeDataValidatorTest.java index 98699b0176..2f4ed4426f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/EdgeDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/EdgeDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.customer.CustomerDao; @@ -34,13 +34,13 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = EdgeDataValidator.class) class EdgeDataValidatorTest { - @MockBean + @MockitoBean EdgeDao edgeDao; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean CustomerDao customerDao; - @SpyBean + @MockitoSpyBean EdgeDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidatorTest.java index 3db9d77469..ab821de252 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/EntityViewDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.customer.CustomerDao; @@ -34,13 +34,13 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = EntityViewDataValidator.class) class EntityViewDataValidatorTest { - @MockBean + @MockitoBean EntityViewDao entityViewDao; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean CustomerDao customerDao; - @SpyBean + @MockitoSpyBean EntityViewDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/ResourceDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/ResourceDataValidatorTest.java index 9072bb5e62..059e966040 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/ResourceDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/ResourceDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.ResourceType; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.id.TenantId; @@ -36,15 +36,15 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = ResourceDataValidator.class) class ResourceDataValidatorTest { - @MockBean + @MockitoBean TbResourceDao resourceDao; - @MockBean + @MockitoBean WidgetTypeDao widgetTypeDao; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean TbTenantProfileCache tenantProfileCache; - @SpyBean + @MockitoSpyBean ResourceDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidatorTest.java index 9107d1f8f2..eb884edbf3 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainType; @@ -34,11 +34,11 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = RuleChainDataValidator.class) class RuleChainDataValidatorTest { - @MockBean + @MockitoBean RuleChainService ruleChainService; - @MockBean + @MockitoBean TenantService tenantService; - @SpyBean + @MockitoSpyBean RuleChainDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantDataValidatorTest.java index c7e4f73ce4..ca1871a1dc 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantDataValidatorTest.java @@ -17,8 +17,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.tenant.TenantDao; @@ -30,9 +30,9 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = TenantDataValidator.class) class TenantDataValidatorTest { - @MockBean + @MockitoBean TenantDao tenantDao; - @SpyBean + @MockitoSpyBean TenantDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java index 170b452fee..9d32fbd49e 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/TenantProfileDataValidatorTest.java @@ -17,8 +17,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; @@ -33,11 +33,11 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = TenantProfileDataValidator.class) class TenantProfileDataValidatorTest { - @MockBean + @MockitoBean TenantProfileDao tenantProfileDao; - @MockBean + @MockitoBean TenantProfileService tenantProfileService; - @SpyBean + @MockitoSpyBean TenantProfileDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidatorTest.java index 3849aa62bf..3904c7d509 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetTypeDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; @@ -34,13 +34,13 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = WidgetTypeDataValidator.class) class WidgetTypeDataValidatorTest { - @MockBean + @MockitoBean WidgetTypeDao widgetTypeDao; - @MockBean + @MockitoBean WidgetsBundleDao widgetsBundleDao; - @MockBean + @MockitoBean TenantService tenantService; - @SpyBean + @MockitoSpyBean WidgetTypeDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidatorTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidatorTest.java index 1affa60415..6ab7728471 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidatorTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/validator/WidgetsBundleDataValidatorTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.service.validator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.widget.WidgetsBundle; import org.thingsboard.server.dao.tenant.TenantService; @@ -33,11 +33,11 @@ import static org.mockito.Mockito.verify; @SpringBootTest(classes = WidgetsBundleDataValidator.class) class WidgetsBundleDataValidatorTest { - @MockBean + @MockitoBean WidgetsBundleDao widgetsBundleDao; - @MockBean + @MockitoBean TenantService tenantService; - @SpyBean + @MockitoSpyBean WidgetsBundleDataValidator validator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepositoryTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepositoryTest.java index b0d946ce3f..863d4ae2e8 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepositoryTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultEntityQueryRepositoryTest.java @@ -19,7 +19,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.support.TransactionTemplate; @@ -31,11 +31,11 @@ import static org.hamcrest.Matchers.equalTo; @SpringBootTest(classes = DefaultEntityQueryRepository.class) public class DefaultEntityQueryRepositoryTest { - @MockBean + @MockitoBean NamedParameterJdbcTemplate jdbcTemplate; - @MockBean + @MockitoBean TransactionTemplate transactionTemplate; - @MockBean + @MockitoBean DefaultQueryLogComponent queryLog; @Autowired diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultQueryLogComponentTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultQueryLogComponentTest.java index 83a06fe568..e47ed5bfbf 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultQueryLogComponentTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/query/DefaultQueryLogComponentTest.java @@ -22,7 +22,7 @@ import org.junit.runner.RunWith; import org.mockito.BDDMockito; import org.mockito.Mockito; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -52,7 +52,7 @@ public class DefaultQueryLogComponentTest { private TenantId tenantId; private SqlQueryContext ctx; - @SpyBean + @MockitoSpyBean private DefaultQueryLogComponent queryLog; @Before diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java index 43c8a064e1..05952e1203 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest.java @@ -22,7 +22,7 @@ import org.mockito.Answers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -53,13 +53,13 @@ public class CassandraBaseTimeseriesDaoPartitioningDaysAlwaysExistsTest { @Autowired CassandraBaseTimeseriesDao tsDao; - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) @Qualifier("CassandraCluster") CassandraCluster cassandraCluster; - @MockBean + @MockitoBean CassandraBufferedRateReadExecutor cassandraBufferedRateReadExecutor; - @MockBean + @MockitoBean CassandraBufferedRateWriteExecutor cassandraBufferedRateWriteExecutor; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java index 5deccec298..83bb802c85 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest.java @@ -22,7 +22,7 @@ import org.mockito.Answers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -53,13 +53,13 @@ public class CassandraBaseTimeseriesDaoPartitioningHoursAlwaysExistsTest { @Autowired CassandraBaseTimeseriesDao tsDao; - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) @Qualifier("CassandraCluster") CassandraCluster cassandraCluster; - @MockBean + @MockitoBean CassandraBufferedRateReadExecutor cassandraBufferedRateReadExecutor; - @MockBean + @MockitoBean CassandraBufferedRateWriteExecutor cassandraBufferedRateWriteExecutor; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java index a742e6cd2c..4f78f5b864 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest.java @@ -22,7 +22,7 @@ import org.mockito.Answers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -52,13 +52,13 @@ public class CassandraBaseTimeseriesDaoPartitioningIndefiniteAlwaysExistsTest { @Autowired CassandraBaseTimeseriesDao tsDao; - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) @Qualifier("CassandraCluster") CassandraCluster cassandraCluster; - @MockBean + @MockitoBean CassandraBufferedRateReadExecutor cassandraBufferedRateReadExecutor; - @MockBean + @MockitoBean CassandraBufferedRateWriteExecutor cassandraBufferedRateWriteExecutor; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java index dd106cb439..455cf2cc00 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest.java @@ -22,7 +22,7 @@ import org.mockito.Answers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -53,13 +53,13 @@ public class CassandraBaseTimeseriesDaoPartitioningMinutesAlwaysExistsTest { @Autowired CassandraBaseTimeseriesDao tsDao; - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) @Qualifier("CassandraCluster") CassandraCluster cassandraCluster; - @MockBean + @MockitoBean CassandraBufferedRateReadExecutor cassandraBufferedRateReadExecutor; - @MockBean + @MockitoBean CassandraBufferedRateWriteExecutor cassandraBufferedRateWriteExecutor; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java index 5699f5d5f7..ce8b66215b 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest.java @@ -22,7 +22,7 @@ import org.junit.runner.RunWith; import org.mockito.Answers; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.junit4.SpringRunner; @@ -63,13 +63,13 @@ public class CassandraBaseTimeseriesDaoPartitioningMonthsAlwaysExistsTest { @MockitoSpyBean CassandraBaseTimeseriesDao tsDao; - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) @Qualifier("CassandraCluster") CassandraCluster cassandraCluster; - @MockBean + @MockitoBean CassandraBufferedRateReadExecutor cassandraBufferedRateReadExecutor; - @MockBean + @MockitoBean CassandraBufferedRateWriteExecutor cassandraBufferedRateWriteExecutor; @Test diff --git a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java index a68daf664a..90575d5b14 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest.java @@ -22,7 +22,7 @@ import org.mockito.Answers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.dao.cassandra.CassandraCluster; @@ -53,13 +53,13 @@ public class CassandraBaseTimeseriesDaoPartitioningYearsAlwaysExistsTest { @Autowired CassandraBaseTimeseriesDao tsDao; - @MockBean(answer = Answers.RETURNS_MOCKS) + @MockitoBean(answers = Answers.RETURNS_MOCKS) @Qualifier("CassandraCluster") CassandraCluster cassandraCluster; - @MockBean + @MockitoBean CassandraBufferedRateReadExecutor cassandraBufferedRateReadExecutor; - @MockBean + @MockitoBean CassandraBufferedRateWriteExecutor cassandraBufferedRateWriteExecutor; @Test From decd71f48fddb58632ac007319777b883a5f6d57 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 11:03:12 +0200 Subject: [PATCH 02/59] Replaced deprecated @MockBean/@SpyBean with @MockitoBean in edqs and coap-server tests Spring Boot 3.4 deprecated @MockBean/@SpyBean in favor of @MockitoBean/@MockitoSpyBean. --- .../server/coapserver/TbCoapDtlsSettingsTest.java | 8 ++++---- .../org/thingsboard/server/edqs/repo/AbstractEDQTest.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/coap-server/src/test/java/org/thingsboard/server/coapserver/TbCoapDtlsSettingsTest.java b/common/coap-server/src/test/java/org/thingsboard/server/coapserver/TbCoapDtlsSettingsTest.java index c75348d97e..f3af7b752f 100644 --- a/common/coap-server/src/test/java/org/thingsboard/server/coapserver/TbCoapDtlsSettingsTest.java +++ b/common/coap-server/src/test/java/org/thingsboard/server/coapserver/TbCoapDtlsSettingsTest.java @@ -18,7 +18,7 @@ package org.thingsboard.server.coapserver; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig; @@ -41,11 +41,11 @@ class TbCoapDtlsSettingsTest { @Autowired TbCoapDtlsSettings coapDtlsSettings; - @MockBean + @MockitoBean SslCredentialsConfig sslCredentialsConfig; - @MockBean + @MockitoBean private TransportService transportService; - @MockBean + @MockitoBean private TbServiceInfoProvider serviceInfoProvider; @Test diff --git a/edqs/src/test/java/org/thingsboard/server/edqs/repo/AbstractEDQTest.java b/edqs/src/test/java/org/thingsboard/server/edqs/repo/AbstractEDQTest.java index adb42203e0..edf8832a33 100644 --- a/edqs/src/test/java/org/thingsboard/server/edqs/repo/AbstractEDQTest.java +++ b/edqs/src/test/java/org/thingsboard/server/edqs/repo/AbstractEDQTest.java @@ -20,7 +20,7 @@ import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.TestExecutionListeners; @@ -81,7 +81,7 @@ public abstract class AbstractEDQTest { protected DefaultEdqsRepository repository; @Autowired protected EdqsMapper edqsMapper; - @MockBean + @MockitoBean private DummyEdqsStatsService edqsStatsService; protected final TenantId tenantId = TenantId.fromUUID(UUID.randomUUID()); From 3fad83d4e4c9c356d635d8f1b98148b67af1eb7a Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 11:09:27 +0200 Subject: [PATCH 03/59] Replaced deprecated @MockBean/@SpyBean with @MockitoBean in application tests Spring Boot 3.4 deprecated @MockBean/@SpyBean in favor of @MockitoBean/@MockitoSpyBean. --- .../controller/AbstractNotifyEntityTest.java | 6 ++-- .../controller/AuditLogControllerTest.java | 6 ++-- ...trollerTest_DedicatedEventsDataSource.java | 4 +-- .../server/controller/AuthControllerTest.java | 4 +-- .../controller/BaseQueueControllerTest.java | 10 +++--- .../controller/DeviceControllerTest.java | 6 ++-- .../controller/EdgeEventControllerTest.java | 4 +-- .../EdqsEntityQueryControllerTest.java | 4 +-- .../server/controller/HomePageApiTest.java | 6 ++-- .../controller/RepositorySettingsTest.java | 4 +-- .../controller/RuleEngineControllerTest.java | 4 +-- .../controller/TenantControllerTest.java | 8 ++--- .../controller/TwoFactorAuthConfigTest.java | 10 +++--- .../server/controller/TwoFactorAuthTest.java | 8 ++--- .../server/controller/WebsocketApiTest.java | 4 +-- .../provision/DeviceProvisionServiceTest.java | 24 ++++++------- .../entitiy/EdqsEntityServiceTest.java | 4 +-- .../alarm/DefaultTbAlarmServiceTest.java | 32 ++++++++--------- .../DefaultTbAlarmCommentServiceTest.java | 34 +++++++++---------- .../service/install/InstallScriptsTest.java | 28 +++++++-------- .../update/DefaultDataUpdateServiceTest.java | 4 +-- .../server/service/job/JobManagerTest.java | 6 ++-- .../notification/NotificationApiTest.java | 4 +-- .../notification/NotificationRuleApiTest.java | 4 +-- .../queue/DefaultTbClusterServiceTest.java | 26 +++++++------- .../service/sms/DefaultSmsServiceTest.java | 4 +-- .../sync/ie/ExportImportServiceSqlTest.java | 6 ++-- .../DefaultTransportApiServiceTest.java | 34 +++++++++---------- .../service/ttl/AlarmsCleanUpServiceTest.java | 6 ++-- .../lwm2m/AbstractLwM2MIntegrationTest.java | 6 ++-- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 4 +-- .../AbstractLwM2MIntegrationDiffPortTest.java | 4 +-- .../mqtt/MqttGatewayRateLimitsTest.java | 4 +-- ...AbstractMqttTimeseriesIntegrationTest.java | 4 +-- 34 files changed, 163 insertions(+), 163 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java index 58bf4b9798..2a03efc2ef 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractNotifyEntityTest.java @@ -18,7 +18,7 @@ package org.thingsboard.server.controller; import lombok.extern.slf4j.Slf4j; import org.mockito.ArgumentMatcher; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EntityType; @@ -53,10 +53,10 @@ import static org.mockito.Mockito.times; @Slf4j public abstract class AbstractNotifyEntityTest extends AbstractWebTest { - @SpyBean + @MockitoSpyBean protected TbClusterService tbClusterService; - @SpyBean + @MockitoSpyBean protected AuditLogService auditLogService; protected final String msgErrorPermission = "You don't have permission to perform this operation!"; diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java index a76da5f161..9c5b46ca70 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest.java @@ -25,7 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.User; @@ -66,9 +66,9 @@ public class AuditLogControllerTest extends AbstractControllerTest { @Autowired private AuditLogDao auditLogDao; @Getter - @SpyBean + @MockitoSpyBean private SqlPartitioningRepository partitioningRepository; - @SpyBean + @MockitoSpyBean private AuditLogsCleanUpService auditLogsCleanUpService; @Value("#{${sql.audit_logs.partition_size} * 60 * 60 * 1000}") diff --git a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java index c594beae98..0660dfe95e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuditLogControllerTest_DedicatedEventsDataSource.java @@ -16,7 +16,7 @@ package org.thingsboard.server.controller; import lombok.Getter; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitioningRepository; @@ -30,7 +30,7 @@ import org.thingsboard.server.dao.sqlts.insert.sql.DedicatedEventsSqlPartitionin public class AuditLogControllerTest_DedicatedEventsDataSource extends AuditLogControllerTest { @Getter - @SpyBean + @MockitoSpyBean private DedicatedEventsSqlPartitioningRepository partitioningRepository; } diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index 9126c42f2f..419f442f87 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -20,7 +20,7 @@ import org.assertj.core.data.Offset; import org.junit.After; import org.junit.Test; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.http.HttpHeaders; import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; @@ -50,7 +50,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DaoSqlTest public class AuthControllerTest extends AbstractControllerTest { - @SpyBean + @MockitoSpyBean private UserCredentialsDao userCredentialsDao; @After diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java index 46a1dba3a7..b01f5f32f2 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseQueueControllerTest.java @@ -24,7 +24,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.actors.ActorSystemContext; @@ -96,15 +96,15 @@ public class BaseQueueControllerTest extends AbstractControllerTest { private RuleEngineStatisticsService ruleEngineStatisticsService; @Autowired private StatsFactory statsFactory; - @SpyBean + @MockitoSpyBean private TimeseriesDao timeseriesDao; @Autowired private QueueStatsService queueStatsService; - @SpyBean + @MockitoSpyBean private PartitionService partitionService; - @SpyBean + @MockitoSpyBean private TimeseriesService timeseriesService; - @SpyBean + @MockitoSpyBean private ActorSystemContext actorSystemContext; @Test diff --git a/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java index 0e404b2857..478b11dd3f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java @@ -31,7 +31,7 @@ import org.mockito.AdditionalAnswers; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.ContextConfiguration; @@ -109,10 +109,10 @@ public class DeviceControllerTest extends AbstractControllerTest { private Tenant savedTenant; private User tenantAdmin; - @SpyBean + @MockitoSpyBean private GatewayNotificationsService gatewayNotificationsService; - @SpyBean + @MockitoSpyBean private DeviceStateService deviceStateService; @Autowired diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java index ba389d3bd6..262d685d74 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java @@ -25,7 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.AttributeScope; @@ -66,7 +66,7 @@ public class EdgeEventControllerTest extends AbstractControllerTest { @Autowired private EdgeEventDao edgeEventDao; - @SpyBean + @MockitoSpyBean private SqlPartitioningRepository partitioningRepository; @Autowired private EdgeEventsCleanUpService edgeEventsCleanUpService; diff --git a/application/src/test/java/org/thingsboard/server/controller/EdqsEntityQueryControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdqsEntityQueryControllerTest.java index 932980a3ca..8d3859b1bd 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdqsEntityQueryControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdqsEntityQueryControllerTest.java @@ -19,7 +19,7 @@ import org.assertj.core.api.ThrowingConsumer; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.common.data.edqs.EdqsState; import org.thingsboard.server.common.data.edqs.EdqsState.EdqsApiMode; @@ -59,7 +59,7 @@ public class EdqsEntityQueryControllerTest extends EntityQueryControllerTest { @Autowired private DiscoveryService discoveryService; - @MockBean // so that we don't do backup for tests + @MockitoBean // so that we don't do backup for tests private EdqsRocksDb edqsRocksDb; @Before diff --git a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java index ee2aefc81a..efe553e8f2 100644 --- a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java @@ -22,7 +22,7 @@ import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.SmsService; @@ -85,10 +85,10 @@ public class HomePageApiTest extends AbstractControllerTest { @Autowired private OAuth2ClientService oAuth2ClientService; - @MockBean + @MockitoBean private MailService mailService; - @MockBean + @MockitoBean private SmsService smsService; private static final int DEFAULT_DASHBOARDS_COUNT = 0; diff --git a/application/src/test/java/org/thingsboard/server/controller/RepositorySettingsTest.java b/application/src/test/java/org/thingsboard/server/controller/RepositorySettingsTest.java index 072e83cc47..3d6c62d701 100644 --- a/application/src/test/java/org/thingsboard/server/controller/RepositorySettingsTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/RepositorySettingsTest.java @@ -18,7 +18,7 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.SettableFuture; import lombok.extern.slf4j.Slf4j; import org.junit.Test; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.thingsboard.server.common.data.sync.vc.RepositoryAuthMethod; import org.thingsboard.server.common.data.sync.vc.RepositorySettings; import org.thingsboard.server.dao.service.DaoSqlTest; @@ -35,7 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DaoSqlTest public class RepositorySettingsTest extends AbstractControllerTest { - @MockBean + @MockitoBean private GitVersionControlQueueService gitVersionControlQueueService; @Test diff --git a/application/src/test/java/org/thingsboard/server/controller/RuleEngineControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/RuleEngineControllerTest.java index 81c74de038..ff75d80d30 100644 --- a/application/src/test/java/org/thingsboard/server/controller/RuleEngineControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/RuleEngineControllerTest.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; @@ -56,7 +56,7 @@ public class RuleEngineControllerTest extends AbstractControllerTest { private final String REQUEST_BODY = "{\"request\":\"download\"}"; private final String RESPONSE_BODY = "{\"response\":\"downloadOk\"}"; - @SpyBean + @MockitoSpyBean private RuleEngineCallService ruleEngineCallService; @Test diff --git a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java index cc217b05d5..cc0f64428e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TenantControllerTest.java @@ -27,7 +27,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatcher; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.ResultActions; import org.thingsboard.common.util.ThingsBoardExecutors; @@ -110,11 +110,11 @@ public class TenantControllerTest extends AbstractControllerTest { ListeningExecutorService executor; - @SpyBean + @MockitoSpyBean private PartitionService partitionService; - @SpyBean + @MockitoSpyBean private ActorSystemContext actorContext; - @SpyBean + @MockitoSpyBean private TbQueueAdmin queueAdmin; @Before diff --git a/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthConfigTest.java b/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthConfigTest.java index c3eb91db85..2a7422880c 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthConfigTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthConfigTest.java @@ -22,8 +22,8 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.cache.CacheManager; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -62,15 +62,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DaoSqlTest public class TwoFactorAuthConfigTest extends AbstractControllerTest { - @SpyBean + @MockitoSpyBean private TotpTwoFaProvider totpTwoFactorAuthProvider; - @MockBean + @MockitoBean private SmsService smsService; @Autowired private CacheManager cacheManager; @Autowired private TwoFaConfigManager twoFaConfigManager; - @SpyBean + @MockitoSpyBean private TwoFactorAuthService twoFactorAuthService; @Before diff --git a/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java b/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java index b20dd570fb..2092c0b7e7 100644 --- a/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/TwoFactorAuthTest.java @@ -23,8 +23,8 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.rule.engine.api.SmsService; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.User; @@ -78,9 +78,9 @@ public class TwoFactorAuthTest extends AbstractControllerTest { @Autowired private TwoFaConfigManager twoFaConfigManager; - @SpyBean + @MockitoSpyBean private TwoFactorAuthService twoFactorAuthService; - @MockBean + @MockitoBean private SmsService smsService; @Autowired private AuditLogService auditLogService; diff --git a/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java b/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java index 6ec0f3ad64..e3b6a6efd8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/WebsocketApiTest.java @@ -28,7 +28,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; @@ -100,7 +100,7 @@ public class WebsocketApiTest extends AbstractControllerTest { @Autowired private TelemetrySubscriptionService tsService; - @SpyBean + @MockitoSpyBean private TimeseriesService timeseriesService; Device device; diff --git a/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java b/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java index de86e46cd0..c5f10ea4b3 100644 --- a/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java @@ -21,8 +21,8 @@ import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.cluster.TbClusterService; @@ -76,25 +76,25 @@ import static org.mockito.Mockito.when; @ContextConfiguration(classes = DeviceProvisionServiceImpl.class) public class DeviceProvisionServiceTest { - @MockBean + @MockitoBean protected TbQueueProducerProvider producerProvider; - @MockBean + @MockitoBean protected TbQueueProducer> ruleEngineMsgProducer; - @MockBean + @MockitoBean protected TbClusterService clusterService; - @MockBean + @MockitoBean protected DeviceProfileService deviceProfileService; - @MockBean + @MockitoBean protected DeviceService deviceService; - @MockBean + @MockitoBean protected DeviceCredentialsService deviceCredentialsService; - @MockBean + @MockitoBean protected AttributesService attributesService; - @MockBean + @MockitoBean protected AuditLogService auditLogService; - @MockBean + @MockitoBean protected PartitionService partitionService; - @SpyBean + @MockitoSpyBean DeviceProvisionServiceImpl service; private String[] chain; diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/EdqsEntityServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/EdqsEntityServiceTest.java index a16cf99c1d..0b7be314a0 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/EdqsEntityServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/EdqsEntityServiceTest.java @@ -19,7 +19,7 @@ import com.google.common.collect.Lists; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; @@ -61,7 +61,7 @@ public class EdqsEntityServiceTest extends EntityServiceTest { @Autowired private EdqsService edqsService; - @MockBean + @MockitoBean private EdqsRocksDb edqsRocksDb; @Before diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java index 4886310750..e5f8061fb8 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java @@ -19,7 +19,7 @@ import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.cluster.TbClusterService; @@ -66,35 +66,35 @@ import static org.mockito.Mockito.when; @SpringJUnitConfig(DefaultTbAlarmService.class) class DefaultTbAlarmServiceTest { - @MockBean + @MockitoBean TbLogEntityActionService logEntityActionService; - @MockBean + @MockitoBean EdgeService edgeService; - @MockBean + @MockitoBean AlarmService alarmService; - @MockBean + @MockitoBean TbAlarmCommentService alarmCommentService; - @MockBean + @MockitoBean AlarmSubscriptionService alarmSubscriptionService; - @MockBean + @MockitoBean CustomerService customerService; - @MockBean + @MockitoBean TbClusterService tbClusterService; - @MockBean + @MockitoBean EntitiesVersionControlService vcService; - @MockBean + @MockitoBean AccessControlService accessControlService; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean AssetService assetService; - @MockBean + @MockitoBean DeviceService deviceService; - @MockBean + @MockitoBean AssetProfileService assetProfileService; - @MockBean + @MockitoBean DeviceProfileService deviceProfileService; - @MockBean + @MockitoBean EntityService entityService; @Autowired diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java index 2c2d2bbdc3..122a939a9d 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarmComment/DefaultTbAlarmCommentServiceTest.java @@ -19,8 +19,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @@ -65,35 +65,35 @@ import static org.mockito.Mockito.when; }) public class DefaultTbAlarmCommentServiceTest { - @MockBean + @MockitoBean protected DbCallbackExecutorService dbExecutor; - @MockBean + @MockitoBean protected TbLogEntityActionService logEntityActionService; - @MockBean + @MockitoBean protected AlarmService alarmService; - @MockBean + @MockitoBean protected AlarmCommentService alarmCommentService; - @MockBean + @MockitoBean protected AlarmSubscriptionService alarmSubscriptionService; - @MockBean + @MockitoBean protected CustomerService customerService; - @MockBean + @MockitoBean protected TbClusterService tbClusterService; - @MockBean + @MockitoBean private AccessControlService accessControlService; - @MockBean + @MockitoBean private TenantService tenantService; - @MockBean + @MockitoBean private AssetService assetService; - @MockBean + @MockitoBean private DeviceService deviceService; - @MockBean + @MockitoBean private AssetProfileService assetProfileService; - @MockBean + @MockitoBean private DeviceProfileService deviceProfileService; - @MockBean + @MockitoBean private EntityService entityService; - @SpyBean + @MockitoSpyBean DefaultTbAlarmCommentService service; @Test diff --git a/application/src/test/java/org/thingsboard/server/service/install/InstallScriptsTest.java b/application/src/test/java/org/thingsboard/server/service/install/InstallScriptsTest.java index fa675fc3f8..5caf2ececd 100644 --- a/application/src/test/java/org/thingsboard/server/service/install/InstallScriptsTest.java +++ b/application/src/test/java/org/thingsboard/server/service/install/InstallScriptsTest.java @@ -20,8 +20,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; @@ -52,30 +52,30 @@ import static org.mockito.BDDMockito.willReturn; @SpringBootTest(classes = {InstallScripts.class, RuleChainDataValidator.class}) class InstallScriptsTest { - @MockBean + @MockitoBean RuleChainService ruleChainService; - @MockBean + @MockitoBean DashboardService dashboardService; - @MockBean + @MockitoBean WidgetTypeService widgetTypeService; - @MockBean + @MockitoBean WidgetsBundleService widgetsBundleService; - @MockBean + @MockitoBean OAuth2ConfigTemplateService oAuth2TemplateService; - @MockBean + @MockitoBean ResourceService resourceService; - @MockBean + @MockitoBean ImageService imageService; - @MockBean + @MockitoBean ResourcesUpdater resourcesUpdater; - @SpyBean + @MockitoSpyBean InstallScripts installScripts; - @MockBean + @MockitoBean TenantService tenantService; - @MockBean + @MockitoBean ApiLimitService apiLimitService; - @SpyBean + @MockitoSpyBean RuleChainDataValidator ruleChainValidator; TenantId tenantId = TenantId.fromUUID(UUID.fromString("9ef79cdf-37a8-4119-b682-2e7ed4e018da")); diff --git a/application/src/test/java/org/thingsboard/server/service/install/update/DefaultDataUpdateServiceTest.java b/application/src/test/java/org/thingsboard/server/service/install/update/DefaultDataUpdateServiceTest.java index a82aad5b62..1690d854d9 100644 --- a/application/src/test/java/org/thingsboard/server/service/install/update/DefaultDataUpdateServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/install/update/DefaultDataUpdateServiceTest.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.ActiveProfiles; import org.thingsboard.common.util.JacksonUtil; @@ -34,7 +34,7 @@ import static org.mockito.BDDMockito.willCallRealMethod; @SpringBootTest(classes = DefaultDataUpdateService.class) class DefaultDataUpdateServiceTest { - @MockBean + @MockitoBean DefaultDataUpdateService service; @BeforeEach diff --git a/application/src/test/java/org/thingsboard/server/service/job/JobManagerTest.java b/application/src/test/java/org/thingsboard/server/service/job/JobManagerTest.java index c17a9f6bfb..b2aa361f27 100644 --- a/application/src/test/java/org/thingsboard/server/service/job/JobManagerTest.java +++ b/application/src/test/java/org/thingsboard/server/service/job/JobManagerTest.java @@ -21,7 +21,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.rule.engine.api.JobManager; import org.thingsboard.server.common.data.Device; @@ -64,10 +64,10 @@ public class JobManagerTest extends AbstractControllerTest { @Autowired private JobManager jobManager; - @SpyBean + @MockitoSpyBean private TestTaskProcessor taskProcessor; - @SpyBean + @MockitoSpyBean private JobStatsService jobStatsService; @Autowired diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index e9e239ec04..a24e303e29 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -24,7 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.http.HttpEntity; import org.springframework.test.web.servlet.ResultActions; import org.springframework.web.client.RestTemplate; @@ -125,7 +125,7 @@ public class NotificationApiTest extends AbstractNotificationApiTest { private NotificationCenter notificationCenter; @Autowired private MicrosoftTeamsNotificationChannel microsoftTeamsNotificationChannel; - @MockBean + @MockitoBean private FirebaseService firebaseService; private static final String TEST_MOBILE_TOKEN = "tenantFcmToken"; diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java index 7175f0981d..d13c5c737a 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java @@ -22,7 +22,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.function.ThrowingRunnable; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.data.util.Pair; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; @@ -137,7 +137,7 @@ import static org.thingsboard.server.common.data.notification.rule.trigger.confi }) public class NotificationRuleApiTest extends AbstractNotificationApiTest { - @SpyBean + @MockitoSpyBean private AlarmSubscriptionService alarmSubscriptionService; @Autowired private DefaultSystemInfoService systemInfoService; diff --git a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java index 8110f6c0e3..63b4c98142 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java @@ -20,8 +20,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.common.util.JacksonUtil; @@ -87,28 +87,28 @@ public class DefaultTbClusterServiceTest { public static final String TRANSPORT = "transport"; - @MockBean + @MockitoBean protected TbDeviceProfileCache deviceProfileCache; - @MockBean + @MockitoBean protected TbAssetProfileCache assetProfileCache; - @MockBean + @MockitoBean protected GatewayNotificationsService gatewayNotificationsService; - @MockBean + @MockitoBean protected EdgeService edgeService; - @MockBean + @MockitoBean protected PartitionService partitionService; - @MockBean + @MockitoBean protected TbQueueProducerProvider producerProvider; - @MockBean + @MockitoBean protected TbRuleEngineProducerService ruleEngineProducerService; - @MockBean + @MockitoBean protected TbTransactionalCache edgeCache; - @MockBean + @MockitoBean protected CalculatedFieldService calculatedFieldService; - @SpyBean + @MockitoSpyBean protected TopicService topicService; - @SpyBean + @MockitoSpyBean protected TbClusterService clusterService; @Test diff --git a/application/src/test/java/org/thingsboard/server/service/sms/DefaultSmsServiceTest.java b/application/src/test/java/org/thingsboard/server/service/sms/DefaultSmsServiceTest.java index 445be6363a..8d23b32946 100644 --- a/application/src/test/java/org/thingsboard/server/service/sms/DefaultSmsServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/sms/DefaultSmsServiceTest.java @@ -22,7 +22,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; @@ -54,7 +54,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. "usage.stats.report.interval=1", }) public class DefaultSmsServiceTest extends AbstractControllerTest { - @SpyBean + @MockitoSpyBean private DefaultSmsService defaultSmsService; @Autowired private AdminSettingsService adminSettingsService; diff --git a/application/src/test/java/org/thingsboard/server/service/sync/ie/ExportImportServiceSqlTest.java b/application/src/test/java/org/thingsboard/server/service/sync/ie/ExportImportServiceSqlTest.java index e19efdf7e0..dde1c2ae27 100644 --- a/application/src/test/java/org/thingsboard/server/service/sync/ie/ExportImportServiceSqlTest.java +++ b/application/src/test/java/org/thingsboard/server/service/sync/ie/ExportImportServiceSqlTest.java @@ -22,7 +22,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.debug.TbMsgGeneratorNode; import org.thingsboard.rule.engine.debug.TbMsgGeneratorNodeConfiguration; @@ -128,9 +128,9 @@ import static org.mockito.Mockito.verify; @DaoSqlTest public class ExportImportServiceSqlTest extends AbstractControllerTest { - @SpyBean + @MockitoSpyBean private EntityActionService entityActionService; - @SpyBean + @MockitoSpyBean private OtaPackageStateService otaPackageStateService; @Autowired diff --git a/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java b/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java index afb77945ab..952172a491 100644 --- a/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java @@ -20,8 +20,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.thingsboard.server.cache.ota.OtaPackageDataCache; @@ -72,35 +72,35 @@ import static org.mockito.Mockito.when; @ContextConfiguration(classes = DefaultTransportApiService.class) public class DefaultTransportApiServiceTest { - @MockBean + @MockitoBean protected TbDeviceProfileCache deviceProfileCache; - @MockBean + @MockitoBean protected TbTenantProfileCache tenantProfileCache; - @MockBean + @MockitoBean protected TbApiUsageStateService apiUsageStateService; - @MockBean + @MockitoBean protected DeviceService deviceService; - @MockBean + @MockitoBean protected DeviceProfileService deviceProfileService; - @MockBean + @MockitoBean protected RelationService relationService; - @MockBean + @MockitoBean protected DeviceCredentialsService deviceCredentialsService; - @MockBean + @MockitoBean protected DbCallbackExecutorService dbCallbackExecutorService; - @MockBean + @MockitoBean protected TbClusterService tbClusterService; - @MockBean + @MockitoBean protected DeviceProvisionService deviceProvisionService; - @MockBean + @MockitoBean protected ResourceService resourceService; - @MockBean + @MockitoBean protected OtaPackageService otaPackageService; - @MockBean + @MockitoBean protected OtaPackageDataCache otaPackageDataCache; - @MockBean + @MockitoBean protected QueueService queueService; - @SpyBean + @MockitoSpyBean DefaultTransportApiService service; private String certificateChain; diff --git a/application/src/test/java/org/thingsboard/server/service/ttl/AlarmsCleanUpServiceTest.java b/application/src/test/java/org/thingsboard/server/service/ttl/AlarmsCleanUpServiceTest.java index fcb948239f..a74db4593c 100644 --- a/application/src/test/java/org/thingsboard/server/service/ttl/AlarmsCleanUpServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/ttl/AlarmsCleanUpServiceTest.java @@ -21,7 +21,7 @@ import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.alarm.Alarm; @@ -50,9 +50,9 @@ import static org.mockito.Mockito.verify; }) public class AlarmsCleanUpServiceTest extends AbstractControllerTest { - @SpyBean + @MockitoSpyBean private AlarmsCleanUpService alarmsCleanUpService; - @SpyBean + @MockitoSpyBean private AlarmService alarmService; @Autowired private AlarmDao alarmDao; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 8d0f0f2af0..9765a50f91 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -36,7 +36,7 @@ import org.junit.Assert; import org.junit.Before; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.http.HttpStatus; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; @@ -132,10 +132,10 @@ import static org.thingsboard.server.transport.lwm2m.ota.AbstractOtaLwM2MIntegra @DaoSqlTest public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportIntegrationTest { - @SpyBean + @MockitoSpyBean protected LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; - @SpyBean + @MockitoSpyBean protected DefaultLwM2mUplinkMsgHandler defaultUplinkMsgHandlerTest; @Autowired diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index ad02b8f8fc..71c48f6d99 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -22,7 +22,7 @@ import org.eclipse.leshan.core.link.LinkParser; import org.eclipse.leshan.core.link.lwm2m.DefaultLwM2mLinkParser; import org.junit.Before; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; @@ -104,7 +104,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected String idVer_19_0_0; - @SpyBean + @MockitoSpyBean protected LwM2mTransportServerHelper lwM2mTransportServerHelperTest; @Before diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java index afb179cc5f..f145d6a62a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java @@ -24,7 +24,7 @@ import org.eclipse.leshan.server.registration.RegistrationStore; import org.eclipse.leshan.server.registration.RegistrationUpdate; import org.junit.Assert; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; @@ -49,7 +49,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient @Slf4j public abstract class AbstractLwM2MIntegrationDiffPortTest extends AbstractSecurityLwM2MIntegrationTest { - @SpyBean + @MockitoSpyBean private RegistrationStore registrationStoreTest; protected void basicTestConnectionDifferentPort(Lwm2mDeviceProfileTransportConfiguration transportConfiguration, diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java index 541ca40072..d2c2b546f7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/MqttGatewayRateLimitsTest.java @@ -22,7 +22,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.TestPropertySource; @@ -71,7 +71,7 @@ public class MqttGatewayRateLimitsTest extends AbstractControllerTest { private Device gateway; private String gatewayAccessToken; - @SpyBean + @MockitoSpyBean private NotificationRuleProcessor notificationRuleProcessor; @Before diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java index ea40a574a5..07837d9d8f 100644 --- a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/telemetry/timeseries/AbstractMqttTimeseriesIntegrationTest.java @@ -21,7 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.DeviceId; @@ -67,7 +67,7 @@ public abstract class AbstractMqttTimeseriesIntegrationTest extends AbstractMqtt protected static final String MALFORMED_JSON_PAYLOAD = "{\"key1\":, \"key2\":true, \"key3\": 3.0, \"key4\": 4," + " \"key5\": {\"someNumber\": 42, \"someArray\": [1,2,3], \"someNestedObject\": {\"key\": \"value\"}}}"; - @SpyBean + @MockitoSpyBean GatewayMetricsService gatewayMetricsService; @Before From 139b32f329c334b20d8601788000f997a32e94c6 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 15:44:10 +0200 Subject: [PATCH 04/59] cleanup(common): add @SafeVarargs, drop raw types and parameterize test collections --- .../server/common/data/util/CollectionsUtil.java | 3 ++- .../org/thingsboard/script/api/tbel/TbUtils.java | 2 +- .../org/thingsboard/script/api/tbel/TbUtilsTest.java | 12 ++++++------ .../org/thingsboard/common/util/ExceptionUtil.java | 1 + 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java b/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java index d0d8828649..125a370678 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/util/CollectionsUtil.java @@ -83,6 +83,7 @@ public class CollectionsUtil { return result; } + @SafeVarargs public static boolean isOneOf(V value, V... others) { if (value == null) { return false; @@ -105,7 +106,7 @@ public class CollectionsUtil { Set newSet = new HashSet<>(existing.size() + 1); newSet.addAll(existing); newSet.add(value); - return (Set) Set.of(newSet.toArray()); + return Set.copyOf(newSet); } } diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java index e206d2d78d..28e0357c3b 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java @@ -1349,7 +1349,7 @@ public class TbUtils { for (byte b : byteArray) { byteList.add(b); } - ExecutionArrayList list = new ExecutionArrayList(byteList, ctx); + ExecutionArrayList list = new ExecutionArrayList<>(byteList, ctx); return list; } diff --git a/common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java b/common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java index 622d298bbb..bc40ced5bb 100644 --- a/common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java +++ b/common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbUtilsTest.java @@ -1308,13 +1308,13 @@ public class TbUtilsTest { } @Test public void setTest() throws ExecutionException, InterruptedException { - Set actual = TbUtils.newSet(ctx); - Set expected = toSet(new byte[]{(byte) 0xDD, (byte) 0xCC, (byte) 0xCC}); + Set actual = TbUtils.newSet(ctx); + Set expected = toSet(new byte[]{(byte) 0xDD, (byte) 0xCC, (byte) 0xCC}); actual.add((byte) 0xDD); actual.add((byte) 0xCC); actual.add((byte) 0xCC); assertTrue(expected.containsAll(actual)); - List list = toList(new byte[]{(byte) 0xDD, (byte) 0xCC, (byte) 0xBB, (byte) 0xAA}); + List list = toList(new byte[]{(byte) 0xDD, (byte) 0xCC, (byte) 0xBB, (byte) 0xAA}); actual.addAll(list); assertEquals(4, actual.size()); assertTrue(actual.containsAll(expected)); @@ -1328,9 +1328,9 @@ public class TbUtilsTest { actual.clear(); assertTrue(actual.isEmpty()); actual = TbUtils.toSet(ctx, list); - Set actualClone = TbUtils.toSet(ctx, list); - Set actualClone_asc = TbUtils.toSet(ctx, list); - Set actualClone_desc = TbUtils.toSet(ctx, list); + Set actualClone = TbUtils.toSet(ctx, list); + Set actualClone_asc = TbUtils.toSet(ctx, list); + Set actualClone_desc = TbUtils.toSet(ctx, list); ((ExecutionLinkedHashSet)actualClone).sort(); ((ExecutionLinkedHashSet)actualClone_asc).sort(true); ((ExecutionLinkedHashSet)actualClone_desc).sort(false); diff --git a/common/util/src/main/java/org/thingsboard/common/util/ExceptionUtil.java b/common/util/src/main/java/org/thingsboard/common/util/ExceptionUtil.java index e5eed02675..7dc1ddde60 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/ExceptionUtil.java +++ b/common/util/src/main/java/org/thingsboard/common/util/ExceptionUtil.java @@ -37,6 +37,7 @@ public class ExceptionUtil { } } + @SafeVarargs public static Exception lookupExceptionInCause(Throwable source, Class... clazzes) { while (source != null) { for (Class clazz : clazzes) { From 8d3f7bf416b5d6b652ef20da2c6e5959bd792229 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 17:03:48 +0200 Subject: [PATCH 05/59] cleanup(dao, transport/lwm2m): parameterize testcontainers and rpc callback types --- .../server/rpc/DefaultLwM2MRpcRequestHandler.java | 12 ++++++------ .../server/dao/AbstractRedisClusterContainer.java | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java index 6980fb6341..c363cd3da5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java @@ -212,7 +212,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { String[] versionedIds = getIdsFromParameters(client, requestMsg); TbLwM2MReadCompositeRequest request = TbLwM2MReadCompositeRequest.builder().versionedIds(versionedIds).timeout(clientContext.getRequestTimeout(client)).build(); var mainCallback = new TbLwM2MReadCompositeCallback(uplinkHandler, logService, client, versionedIds); - var rpcCallback = new RpcReadResponseCompositeCallback(transportService, client, requestMsg, mainCallback); + var rpcCallback = new RpcReadResponseCompositeCallback<>(transportService, client, requestMsg, mainCallback); downlinkHandler.sendReadCompositeRequest(client, request, rpcCallback); } @@ -323,7 +323,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { } else if (path.isResource()) { validateResource(client, newNodes, nodes, key , value); } else if (path.isObjectInstance() && value instanceof Map) { - ((Map) value).forEach((k, v) -> { + ((Map) value).forEach((k, v) -> { validateResource(client, newNodes, nodes, validateResourceId (key, k.toString(), nodes), v); }); } else { @@ -337,7 +337,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { return newNodes; } - private void validateResource(LwM2mClient client, Map newNodes, Map nodes, String resourceId , Object value) { + private void validateResource(LwM2mClient client, Map newNodes, Map nodes, String resourceId , Object value) { if (value instanceof Map) { ((Map) value).forEach((k, v) -> { setValueToCompositeNodes(client, newNodes, nodes, validateResourceId (resourceId, k.toString(), nodes), v); @@ -347,7 +347,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { } } - private String validateResourceId (String key, String id, Map nodes) { + private String validateResourceId (String key, String id, Map nodes) { try { Integer.parseInt(id); return key + "/" + id; @@ -357,7 +357,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { } } - private void setValueToCompositeNodes (LwM2mClient client, Map newNodes, Map nodes, String versionedId , Object value) { + private void setValueToCompositeNodes (LwM2mClient client, Map newNodes, Map nodes, String versionedId , Object value) { // validate value. Must be only primitive, not JsonObject or JsonArray try { JsonElement element = JsonUtils.parse(value); @@ -388,7 +388,7 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler { String[] versionedIds = getIdsFromParameters(client, requestMsg); TbLwM2MObserveCompositeRequest request = TbLwM2MObserveCompositeRequest.builder().versionedIds(versionedIds).timeout(clientContext.getRequestTimeout(client)).build(); var mainCallback = new TbLwM2MObserveCompositeCallback(uplinkHandler, logService, client, versionedIds); - var rpcCallback = new RpcObserveResponseCompositeCallback(transportService, client, requestMsg, mainCallback); + var rpcCallback = new RpcObserveResponseCompositeCallback<>(transportService, client, requestMsg, mainCallback); downlinkHandler.sendObserveCompositeRequest(client, request, rpcCallback); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractRedisClusterContainer.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractRedisClusterContainer.java index 827e50a5cc..1f057c802b 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/AbstractRedisClusterContainer.java +++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractRedisClusterContainer.java @@ -40,17 +40,17 @@ public class AbstractRedisClusterContainer { ); @ClassRule(order = 1) - public static GenericContainer redis1 = new GenericContainer(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6371").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); + public static GenericContainer redis1 = new GenericContainer<>(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6371").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); @ClassRule(order = 2) - public static GenericContainer redis2 = new GenericContainer(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6372").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); + public static GenericContainer redis2 = new GenericContainer<>(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6372").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); @ClassRule(order = 3) - public static GenericContainer redis3 = new GenericContainer(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6373").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); + public static GenericContainer redis3 = new GenericContainer<>(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6373").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); @ClassRule(order = 4) - public static GenericContainer redis4 = new GenericContainer(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6374").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); + public static GenericContainer redis4 = new GenericContainer<>(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6374").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); @ClassRule(order = 5) - public static GenericContainer redis5 = new GenericContainer(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6375").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); + public static GenericContainer redis5 = new GenericContainer<>(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6375").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); @ClassRule(order = 6) - public static GenericContainer redis6 = new GenericContainer(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6376").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); + public static GenericContainer redis6 = new GenericContainer<>(IMAGE).withEnv(ENVS).withEnv("VALKEY_PORT_NUMBER", "6376").withNetworkMode("host").withLogConsumer(AbstractRedisClusterContainer::consumeLog); @ClassRule(order = 100) From 6696879a54ec6f1dbc57aa1f7e7b4d6434eb2c13 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 22:07:16 +0200 Subject: [PATCH 06/59] cleanup(application): parameterize Set and Predicate fields in lwm2m rpc integration test base --- .../lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index ad02b8f8fc..1e3b6fcbe7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -78,16 +78,16 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg protected final LinkParser linkParser = new DefaultLwM2mLinkParser(); protected String CONFIG_PROFILE_WITH_PARAMS_RPC; - public Set expectedObjects; - public Set expectedObjectIdVers; - public Set expectedInstances; - public Set expectedObjectIdVerInstances; + public Set expectedObjects; + public Set expectedObjectIdVers; + public Set expectedInstances; + public Set expectedObjectIdVerInstances; protected String objectInstanceIdVer_1; protected String objectIdVer_0; protected String objectIdVer_1; protected String objectIdVer_2; - private static final Predicate PREDICATE_3 = path -> (!((String) path).startsWith("/" + TEMPERATURE_SENSOR) && ((String) path).startsWith("/" + DEVICE)); + private static final Predicate PREDICATE_3 = path -> (!((String) path).startsWith("/" + TEMPERATURE_SENSOR) && ((String) path).startsWith("/" + DEVICE)); protected String objectIdVer_3; protected String objectInstanceIdVer_3; protected String objectInstanceIdVer_5; From de1f1a2d9dbdafc743f68b0252a632490d89a23f Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Wed, 22 Apr 2026 22:56:52 +0200 Subject: [PATCH 07/59] cleanup(tests, transport/lwm2m): use ArgumentCaptor.captor() and parameterize path list --- .../downlink/DefaultLwM2mDownlinkMsgHandler.java | 2 +- .../service/TransportActivityManagerTest.java | 4 ++-- .../rule/engine/flow/TbCheckpointNodeTest.java | 2 +- .../rule/engine/kafka/TbKafkaNodeTest.java | 2 +- .../rule/engine/metadata/TbGetTelemetryNodeTest.java | 12 ++++++------ .../telemetry/TbMsgDeleteAttributesNodeTest.java | 2 +- .../engine/transform/TbMsgDeduplicationNodeTest.java | 10 +++++----- .../engine/transform/TbSplitArrayMsgNodeTest.java | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index 8f638cfa2a..6d6eea28ab 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -815,7 +815,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im LwM2mPath pathSingleOb = singleObs.getPath(); LwM2mPath pathObjectId = new LwM2mPath(objectId); if (!pathSingleOb.toString().equals(objectId)) { - List paths = Arrays.asList(pathSingleOb, pathObjectId); + List paths = Arrays.asList(pathSingleOb, pathObjectId); try { LwM2mPath.validateNotOverlapping(paths); } catch (IllegalArgumentException e){ diff --git a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/service/TransportActivityManagerTest.java b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/service/TransportActivityManagerTest.java index 3b3ce6e600..35ddba5d90 100644 --- a/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/service/TransportActivityManagerTest.java +++ b/common/transport/transport-api/src/test/java/org/thingsboard/server/common/transport/service/TransportActivityManagerTest.java @@ -122,7 +122,7 @@ public class TransportActivityManagerTest { // THEN ArgumentCaptor sessionInfoCaptor = ArgumentCaptor.forClass(TransportProtos.SessionInfoProto.class); ArgumentCaptor subscriptionInfoCaptor = ArgumentCaptor.forClass(TransportProtos.SubscriptionInfoProto.class); - ArgumentCaptor> callbackCaptor = ArgumentCaptor.forClass(TransportServiceCallback.class); + ArgumentCaptor> callbackCaptor = ArgumentCaptor.captor(); verify(transportServiceMock).process(sessionInfoCaptor.capture(), subscriptionInfoCaptor.capture(), callbackCaptor.capture()); @@ -166,7 +166,7 @@ public class TransportActivityManagerTest { // THEN ArgumentCaptor sessionInfoCaptor = ArgumentCaptor.forClass(TransportProtos.SessionInfoProto.class); ArgumentCaptor subscriptionInfoCaptor = ArgumentCaptor.forClass(TransportProtos.SubscriptionInfoProto.class); - ArgumentCaptor> callbackCaptor = ArgumentCaptor.forClass(TransportServiceCallback.class); + ArgumentCaptor> callbackCaptor = ArgumentCaptor.captor(); verify(transportServiceMock).process(sessionInfoCaptor.capture(), subscriptionInfoCaptor.capture(), callbackCaptor.capture()); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java index ab0f358684..7c47477fee 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java @@ -114,7 +114,7 @@ public class TbCheckpointNodeTest extends AbstractRuleNodeUpgradeTest { .build(); node.onMsg(ctxMock, msg); - ArgumentCaptor> onFailure = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> onFailure = ArgumentCaptor.captor(); then(ctxMock).should().enqueueForTellNext(eq(msg), eq(DataConstants.HP_QUEUE_NAME), eq(TbNodeConnectionType.SUCCESS), any(), onFailure.capture()); String errorMsg = "Something went wrong."; onFailure.getValue().accept(new RuntimeException(errorMsg)); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java index 5df7e1be7b..392821b767 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/kafka/TbKafkaNodeTest.java @@ -420,7 +420,7 @@ public class TbKafkaNodeTest extends AbstractRuleNodeUpgradeTest { } private void verifyProducerRecord(String expectedTopic, String expectedKey, String expectedValue, Headers expectedHeaders) { - ArgumentCaptor> actualRecordCaptor = ArgumentCaptor.forClass(ProducerRecord.class); + ArgumentCaptor> actualRecordCaptor = ArgumentCaptor.captor(); then(producerMock).should().send(actualRecordCaptor.capture(), any()); ProducerRecord actualRecord = actualRecordCaptor.getValue(); assertThat(actualRecord.topic()).isEqualTo(expectedTopic); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java index ce3a1b5b22..5de65535e7 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java @@ -219,7 +219,7 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctxMock, msg); // THEN - ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.captor(); then(timeseriesServiceMock).should().findAll(eq(TENANT_ID), eq(DEVICE_ID), actualReadTsKvQueryList.capture()); ReadTsKvQuery actualReadTsKvQuery = actualReadTsKvQueryList.getValue().get(0); assertThat(actualReadTsKvQuery.getStartTs()).isEqualTo(startTs); @@ -246,7 +246,7 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctxMock, msg); // THEN - ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.captor(); then(timeseriesServiceMock).should().findAll(eq(TENANT_ID), eq(DEVICE_ID), actualReadTsKvQueryList.capture()); ReadTsKvQuery actualReadTsKvQuery = actualReadTsKvQueryList.getValue().get(0); assertThat(actualReadTsKvQuery.getStartTs()).isEqualTo(ts - TimeUnit.MINUTES.toMillis(config.getStartInterval())); @@ -275,7 +275,7 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctxMock, msg); // THEN - ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.captor(); then(timeseriesServiceMock).should().findAll(eq(TENANT_ID), eq(DEVICE_ID), actualReadTsKvQueryList.capture()); List actualKeys = actualReadTsKvQueryList.getValue().stream().map(TsKvQuery::getKey).toList(); assertThat(actualKeys).containsExactlyInAnyOrder("temperature", "humidity", "pressure"); @@ -305,7 +305,7 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctxMock, msg); // THEN - ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.captor(); then(timeseriesServiceMock).should().findAll(eq(TENANT_ID), eq(DEVICE_ID), actualReadTsKvQueryList.capture()); ReadTsKvQuery actualReadTsKvQuery = actualReadTsKvQueryList.getValue().get(0); aggregationStepVerifier.accept(actualReadTsKvQuery); @@ -340,7 +340,7 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctxMock, msg); // THEN - ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.captor(); then(timeseriesServiceMock).should().findAll(eq(TENANT_ID), eq(DEVICE_ID), actualReadTsKvQueryList.capture()); ReadTsKvQuery actualReadTsKvQuery = actualReadTsKvQueryList.getValue().get(0); limitInQueryVerifier.accept(actualReadTsKvQuery); @@ -385,7 +385,7 @@ public class TbGetTelemetryNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctxMock, msg); // THEN - ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.forClass(List.class); + ArgumentCaptor> actualReadTsKvQueryList = ArgumentCaptor.captor(); then(timeseriesServiceMock).should().findAll(eq(TENANT_ID), eq(DEVICE_ID), actualReadTsKvQueryList.capture()); ReadTsKvQuery actualReadTsKvQuery = actualReadTsKvQueryList.getValue().get(0); orderInQueryVerifier.accept(actualReadTsKvQuery); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java index b03794c39d..105962fd1e 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java @@ -147,7 +147,7 @@ public class TbMsgDeleteAttributesNodeTest { node.onMsg(ctx, msg); ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); if (sendAttributesDeletedNotification) { diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java index ec71819878..8fd2868f61 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java @@ -192,7 +192,7 @@ public class TbMsgDeduplicationNodeTest extends AbstractRuleNodeUpgradeTest { ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); verify(ctx, times(msgCount)).ack(any()); verify(ctx, times(1)).tellFailure(eq(msgToReject), any()); @@ -248,7 +248,7 @@ public class TbMsgDeduplicationNodeTest extends AbstractRuleNodeUpgradeTest { ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); verify(ctx, times(msgCount)).ack(any()); verify(ctx, times(1)).tellFailure(eq(msgToReject), any()); @@ -293,7 +293,7 @@ public class TbMsgDeduplicationNodeTest extends AbstractRuleNodeUpgradeTest { ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); verify(ctx, times(msgCount)).ack(any()); verify(node, times(msgCount + wantedNumberOfTellSelfInvocation)).onMsg(eq(ctx), any()); @@ -339,7 +339,7 @@ public class TbMsgDeduplicationNodeTest extends AbstractRuleNodeUpgradeTest { ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); verify(ctx, times(msgCount)).ack(any()); verify(node, times(msgCount + wantedNumberOfTellSelfInvocation)).onMsg(eq(ctx), any()); @@ -393,7 +393,7 @@ public class TbMsgDeduplicationNodeTest extends AbstractRuleNodeUpgradeTest { ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); verify(ctx, times(msgCount)).ack(any()); verify(node, times(msgCount + wantedNumberOfTellSelfInvocation)).onMsg(eq(ctx), any()); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java index 5cd88c8ea9..b178def66e 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java @@ -114,7 +114,7 @@ public class TbSplitArrayMsgNodeTest { if (dataNode.size() > 1) { ArgumentCaptor successCaptor = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor> failureCaptor = ArgumentCaptor.forClass(Consumer.class); + ArgumentCaptor> failureCaptor = ArgumentCaptor.captor(); verify(ctx, times(dataNode.size())).enqueueForTellNext(any(), anyString(), successCaptor.capture(), failureCaptor.capture()); for (Runnable valueCaptor : successCaptor.getAllValues()) { valueCaptor.run(); From e31d04956ce27c61a0bbe1428b930777eba62c1f Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Thu, 23 Apr 2026 10:20:35 +0200 Subject: [PATCH 08/59] Fixed tests by adding context configuration, swapping @MockitoSpyBean for @MockitoBean and adding missing dependencies. Signed-off-by: Oleksandra Matviienko --- .../provision/DeviceProvisionServiceTest.java | 17 ++++++++++++- .../queue/DefaultTbClusterServiceTest.java | 19 ++++++++++++++- .../DefaultTransportApiServiceTest.java | 24 ++++++++++++++++++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java b/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java index c5f10ea4b3..4f2eaa5147 100644 --- a/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java @@ -73,9 +73,24 @@ import static org.mockito.Mockito.when; @Slf4j @RunWith(SpringRunner.class) -@ContextConfiguration(classes = DeviceProvisionServiceImpl.class) +@ContextConfiguration(classes = DeviceProvisionServiceTest.ContextConfiguration.class) public class DeviceProvisionServiceTest { + @org.springframework.context.annotation.Configuration + static class ContextConfiguration { + @org.springframework.context.annotation.Bean + public DeviceProvisionServiceImpl deviceProvisionService(TbQueueProducerProvider producerProvider, + DeviceProfileService deviceProfileService, + DeviceService deviceService, + DeviceCredentialsService deviceCredentialsService, + AttributesService attributesService, + AuditLogService auditLogService, + PartitionService partitionService) { + return new DeviceProvisionServiceImpl(producerProvider, deviceProfileService, deviceService, + deviceCredentialsService, attributesService, auditLogService, partitionService); + } + } + @MockitoBean protected TbQueueProducerProvider producerProvider; @MockitoBean diff --git a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java index 63b4c98142..79b31acf78 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java @@ -56,6 +56,7 @@ import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.TopicService; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.service.gateway_device.GatewayNotificationsService; +import org.thingsboard.server.service.ota.OtaPackageStateService; import org.thingsboard.server.service.profile.TbAssetProfileCache; import org.thingsboard.server.service.profile.TbDeviceProfileCache; @@ -67,6 +68,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -106,11 +108,26 @@ public class DefaultTbClusterServiceTest { @MockitoBean protected CalculatedFieldService calculatedFieldService; - @MockitoSpyBean + @MockitoBean protected TopicService topicService; + @MockitoBean + protected OtaPackageStateService otaPackageStateService; @MockitoSpyBean protected TbClusterService clusterService; + @org.junit.Before + public void setUp() { + lenient().when(topicService.getNotificationsTopic(any(), any())).thenAnswer(invocation -> { + ServiceType serviceType = invocation.getArgument(0); + String serviceId = invocation.getArgument(1); + return new TopicPartitionInfo(serviceType.name().toLowerCase() + ".notifications." + serviceId, null, null, false); + }); + lenient().when(topicService.getCalculatedFieldNotificationsTopic(any())).thenAnswer(invocation -> { + String serviceId = invocation.getArgument(0); + return new TopicPartitionInfo("calculated_field.notifications." + serviceId, null, null, false); + }); + } + @Test public void testOnQueueChangeSingleMonolith() { when(partitionService.getAllServiceIds(ServiceType.TB_RULE_ENGINE)).thenReturn(Sets.newHashSet(MONOLITH)); diff --git a/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java b/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java index 952172a491..6b667cc811 100644 --- a/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java @@ -69,9 +69,31 @@ import static org.mockito.Mockito.when; @Slf4j @RunWith(SpringRunner.class) -@ContextConfiguration(classes = DefaultTransportApiService.class) +@ContextConfiguration(classes = DefaultTransportApiServiceTest.ContextConfiguration.class) public class DefaultTransportApiServiceTest { + @org.springframework.context.annotation.Configuration + static class ContextConfiguration { + @org.springframework.context.annotation.Bean + public DefaultTransportApiService defaultTransportApiService(TbDeviceProfileCache deviceProfileCache, + TbTenantProfileCache tenantProfileCache, + TbApiUsageStateService apiUsageStateService, + DeviceService deviceService, + DeviceProfileService deviceProfileService, + RelationService relationService, + DeviceCredentialsService deviceCredentialsService, + TbClusterService tbClusterService, + DeviceProvisionService deviceProvisionService, + ResourceService resourceService, + OtaPackageService otaPackageService, + OtaPackageDataCache otaPackageDataCache, + QueueService queueService) { + return new DefaultTransportApiService(deviceProfileCache, tenantProfileCache, apiUsageStateService, + deviceService, deviceProfileService, relationService, deviceCredentialsService, tbClusterService, + deviceProvisionService, resourceService, otaPackageService, otaPackageDataCache, queueService); + } + } + @MockitoBean protected TbDeviceProfileCache deviceProfileCache; @MockitoBean From e7751a0bf516246361cbe0e6896f974d6254caa5 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Thu, 23 Apr 2026 15:11:11 +0200 Subject: [PATCH 09/59] Replaced deprecated X509Certificate.getSubjectDN()/getIssuerDN() with getSubjectX500Principal()/getIssuerX500Principal() in CertPemCredentials Uses X500Principal.getName(X500Principal.RFC1779) to keep DN output byte-identical to the old sun.security.x509.X500Name format; expected test strings unchanged. Removes 7 getSubjectDN() and 1 getIssuerDN() deprecation warnings in rule-engine-components. --- .../rule/engine/credentials/CertPemCredentials.java | 5 +++-- .../engine/credentials/CertPemCredentialsTest.java | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java index 81def5a96b..46d844d2c4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.StringUtils; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; +import javax.security.auth.x500.X500Principal; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.CertPath; @@ -77,7 +78,7 @@ public class CertPemCredentials implements ClientCredentials { KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); caKeyStore.load(null, null); for (X509Certificate caCert : caCerts) { - caKeyStore.setCertificateEntry(CA_CERT_CERT_ALIAS_PREFIX + caCert.getSubjectDN().getName(), caCert); + caKeyStore.setCertificateEntry(CA_CERT_CERT_ALIAS_PREFIX + caCert.getSubjectX500Principal().getName(X500Principal.RFC1779), caCert); } TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); @@ -99,7 +100,7 @@ public class CertPemCredentials implements ClientCredentials { keyStore.load(null); List unique = certificates.stream().distinct().collect(Collectors.toList()); for (X509Certificate cert : unique) { - keyStore.setCertificateEntry(CERT_ALIAS_PREFIX + cert.getSubjectDN().getName(), cert); + keyStore.setCertificateEntry(CERT_ALIAS_PREFIX + cert.getSubjectX500Principal().getName(X500Principal.RFC1779), cert); } if (privateKey != null) { diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java index cd0d508fec..634b5d8754 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java @@ -23,6 +23,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.thingsboard.common.util.SslUtil; +import javax.security.auth.x500.X500Principal; import java.io.File; import java.io.IOException; import java.security.Key; @@ -49,13 +50,13 @@ public class CertPemCredentialsTest { Assertions.assertEquals(4, x509Certificates.size()); Assertions.assertEquals("CN=*.thingsboard.cloud, O=\"ThingsBoard, Inc.\", ST=New York, C=US", - x509Certificates.get(0).getSubjectDN().getName()); + x509Certificates.get(0).getSubjectX500Principal().getName(X500Principal.RFC1779)); Assertions.assertEquals("CN=Sectigo ECC Organization Validation Secure Server CA, O=Sectigo Limited, L=Salford, ST=Greater Manchester, C=GB", - x509Certificates.get(1).getSubjectDN().getName()); + x509Certificates.get(1).getSubjectX500Principal().getName(X500Principal.RFC1779)); Assertions.assertEquals("CN=USERTrust ECC Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US", - x509Certificates.get(2).getSubjectDN().getName()); + x509Certificates.get(2).getSubjectX500Principal().getName(X500Principal.RFC1779)); Assertions.assertEquals("CN=AAA Certificate Services, O=Comodo CA Limited, L=Salford, ST=Greater Manchester, C=GB", - x509Certificates.get(3).getSubjectDN().getName()); + x509Certificates.get(3).getSubjectX500Principal().getName(X500Principal.RFC1779)); } @Test @@ -66,7 +67,7 @@ public class CertPemCredentialsTest { Assertions.assertEquals(1, x509Certificates.size()); Assertions.assertEquals("CN=*.thingsboard.cloud, O=\"ThingsBoard, Inc.\", ST=New York, C=US", - x509Certificates.get(0).getSubjectDN().getName()); + x509Certificates.get(0).getSubjectX500Principal().getName(X500Principal.RFC1779)); } @Test @@ -103,7 +104,7 @@ public class CertPemCredentialsTest { List certs = SslUtil.readCertFile(certContent); for (X509Certificate cert : certs) { - String alias = CERT_ALIAS_PREFIX + cert.getIssuerDN().getName(); + String alias = CERT_ALIAS_PREFIX + cert.getIssuerX500Principal().getName(X500Principal.RFC1779); Certificate certificate = keyStore.getCertificate(alias); Assertions.assertNotNull(certificate); Assertions.assertEquals(new String(cert.getEncoded()), new String(certificate.getEncoded())); From 15cca51c42f83691a1c68995dab6906f3d88f336 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Fri, 24 Apr 2026 08:54:24 +0200 Subject: [PATCH 10/59] chore(build): silence Lombok @Builder ignore-initializer warnings Added @Builder.Default to 5 fields with initializers in MobileLayoutConfig (pages) and DefaultTenantProfileConfiguration (maxCalculatedFieldsPerEntity, maxArgumentsPerCF, maxStateSizeInKBytes, maxSingleValueArgumentSizeInKBytes). Dropped the redundant `= 0` on Task.attempt (int default is already 0) to clear the same anomaly on @SuperBuilder. Eliminates 6 "@Builder/@SuperBuilder will ignore the initializing expression" warnings from #15481 Tier 2. `[WARNING]` total drops 843 -> 837, `[ERROR]` unchanged at 0. --- .../org/thingsboard/server/common/data/job/task/Task.java | 2 +- .../server/common/data/mobile/layout/MobileLayoutConfig.java | 1 + .../tenant/profile/DefaultTenantProfileConfiguration.java | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/job/task/Task.java b/common/data/src/main/java/org/thingsboard/server/common/data/job/task/Task.java index 8f3e0d814b..a881780012 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/job/task/Task.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/job/task/Task.java @@ -46,7 +46,7 @@ public abstract class Task { public Task() { } - private int attempt = 0; + private int attempt; public abstract R toFailed(Throwable error); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/layout/MobileLayoutConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/layout/MobileLayoutConfig.java index a45fd90838..8cf0bfb618 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/layout/MobileLayoutConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/layout/MobileLayoutConfig.java @@ -38,6 +38,7 @@ public class MobileLayoutConfig { @Schema(description = "List of pages") @JsonView(Views.Public.class) @Valid + @Builder.Default private List pages = new ArrayList<>(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java index e8dbfd1584..fd13317a38 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java @@ -168,16 +168,20 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura private double warnThreshold; + @Builder.Default @Schema(example = "5") private long maxCalculatedFieldsPerEntity = 5; + @Builder.Default @Schema(example = "10") private long maxArgumentsPerCF = 10; @Builder.Default @Min(value = 1, message = "must be at least 1") @Schema(example = "1000") private long maxDataPointsPerRollingArg = 1000; + @Builder.Default @Schema(example = "32") private long maxStateSizeInKBytes = 32; + @Builder.Default @Schema(example = "2") private long maxSingleValueArgumentSizeInKBytes = 2; From d7dc035ebc3f0cda4bec345a89e9b521baea27a0 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Fri, 24 Apr 2026 10:09:17 +0200 Subject: [PATCH 11/59] chore(build): silence Lombok @EqualsAndHashCode callSuper warnings --- .../server/service/cf/ctx/state/ScriptCalculatedFieldState.java | 2 ++ .../server/service/cf/ctx/state/SimpleCalculatedFieldState.java | 2 ++ .../main/java/org/thingsboard/server/common/data/EventInfo.java | 2 ++ .../java/org/thingsboard/server/common/data/HomeDashboard.java | 2 ++ .../java/org/thingsboard/server/common/data/TenantInfo.java | 2 ++ .../org/thingsboard/server/common/data/alarm/AlarmComment.java | 1 + .../data/device/data/CoapDeviceTransportConfiguration.java | 2 ++ .../data/device/data/Lwm2mDeviceTransportConfiguration.java | 2 ++ .../lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java | 2 ++ .../java/org/thingsboard/server/common/data/edge/EdgeInfo.java | 2 ++ .../thingsboard/server/common/data/edqs/fields/AssetFields.java | 2 ++ .../server/common/data/edqs/fields/AssetProfileFields.java | 2 ++ .../server/common/data/edqs/fields/CustomerFields.java | 2 ++ .../server/common/data/edqs/fields/DashboardFields.java | 2 ++ .../server/common/data/edqs/fields/DeviceFields.java | 2 ++ .../server/common/data/edqs/fields/DeviceProfileFields.java | 2 ++ .../thingsboard/server/common/data/edqs/fields/EdgeFields.java | 2 ++ .../server/common/data/edqs/fields/EntityViewFields.java | 2 ++ .../server/common/data/edqs/fields/QueueStatsFields.java | 2 ++ .../server/common/data/edqs/fields/RuleChainFields.java | 2 ++ .../server/common/data/edqs/fields/TenantFields.java | 2 ++ .../server/common/data/edqs/fields/TenantProfileFields.java | 2 ++ .../thingsboard/server/common/data/edqs/fields/UserFields.java | 2 ++ .../thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java | 2 ++ .../thingsboard/server/common/data/query/AlarmCountQuery.java | 2 ++ .../java/org/thingsboard/server/common/data/queue/Queue.java | 2 ++ .../org/thingsboard/server/common/data/rule/RuleNodeState.java | 2 ++ .../thingsboard/server/common/data/widget/WidgetTypeInfo.java | 2 ++ .../server/transport/mqtt/limits/GatewaySessionLimits.java | 2 ++ .../server/dao/model/sqlts/latest/TsKvLatestEntity.java | 2 ++ .../rule/engine/action/TbClearAlarmNodeConfiguration.java | 2 ++ .../rule/engine/action/TbCreateAlarmNodeConfiguration.java | 2 ++ .../rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java | 2 ++ .../rule/engine/mqtt/azure/AzureIotHubSasCredentials.java | 2 ++ .../rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java | 2 ++ 35 files changed, 69 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java index 24f3acd4a7..be95922dbb 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java @@ -20,6 +20,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.thingsboard.script.api.tbel.TbelCfArg; @@ -35,6 +36,7 @@ import java.util.List; import java.util.Map; @Data +@EqualsAndHashCode(callSuper = false) @Slf4j @NoArgsConstructor public class ScriptCalculatedFieldState extends BaseCalculatedFieldState { diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java index 0d018f5def..62c3f840f4 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.script.api.tbel.TbUtils; @@ -33,6 +34,7 @@ import java.util.List; import java.util.Map; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor public class SimpleCalculatedFieldState extends BaseCalculatedFieldState { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java index 9ca3957050..e0bdde1dd8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EventId; import org.thingsboard.server.common.data.id.TenantId; @@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.id.TenantId; * @author Andrew Shvayka */ @Data +@EqualsAndHashCode(callSuper = false) @Schema public class EventInfo extends BaseData { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java index ce9c8fce78..df2cdf2bf5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java @@ -17,9 +17,11 @@ package org.thingsboard.server.common.data; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; @Schema @Data +@EqualsAndHashCode(callSuper = false) public class HomeDashboard extends Dashboard { public static final String HIDE_DASHBOARD_TOOLBAR_DESCRIPTION = "Hide dashboard toolbar flag. Useful for rendering dashboards on mobile."; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java index 4126b1acdd..8f38ecd750 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java @@ -17,10 +17,12 @@ package org.thingsboard.server.common.data; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.TenantId; @Schema @Data +@EqualsAndHashCode(callSuper = false) public class TenantInfo extends Tenant { @Schema(description = "Tenant Profile name", example = "Default") private String tenantProfileName; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 0a011c287f..29269e5bd8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -34,6 +34,7 @@ import java.io.Serial; @Schema @Data +@EqualsAndHashCode(callSuper = false) @Builder @AllArgsConstructor public class AlarmComment extends BaseData implements HasName { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java index 3f23e4fe14..662887c08c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java @@ -19,12 +19,14 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.DeviceTransportType; import java.util.HashMap; import java.util.Map; @Data +@EqualsAndHashCode(callSuper = false) public class CoapDeviceTransportConfiguration extends PowerSavingConfiguration implements DeviceTransportConfiguration { private static final long serialVersionUID = 6061442236008925609L; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java index 079ceffada..1c53412ef9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java @@ -19,12 +19,14 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.DeviceTransportType; import java.util.HashMap; import java.util.Map; @Data +@EqualsAndHashCode(callSuper = false) public class Lwm2mDeviceTransportConfiguration extends PowerSavingConfiguration implements DeviceTransportConfiguration { @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java index 85c1e97e24..14ef402718 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java @@ -17,9 +17,11 @@ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.EqualsAndHashCode; @Schema @Data +@EqualsAndHashCode(callSuper = false) public class LwM2MServerSecurityConfigDefault extends LwM2MServerSecurityConfig { @Schema(description = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", accessMode = Schema.AccessMode.READ_ONLY) protected String securityHost; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java index dd751b8b9d..5dbd0212b3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java @@ -16,9 +16,11 @@ package org.thingsboard.server.common.data.edge; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.EdgeId; @Data +@EqualsAndHashCode(callSuper = false) public class EdgeInfo extends Edge { private String customerTitle; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java index 40ad22ed19..d05147b4d7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -26,6 +27,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class AssetFields extends AbstractEntityFields implements ProfileAwareFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java index ce91aac9d0..c519daa800 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java @@ -16,12 +16,14 @@ package org.thingsboard.server.common.data.edqs.fields; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import java.util.UUID; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class AssetProfileFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java index e2cdf8f295..c324f0f1ab 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class CustomerFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java index 4131d58e98..608a64436e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -28,6 +29,7 @@ import java.util.UUID; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class DashboardFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java index 90400ae70d..ef8aee952b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -26,6 +27,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class DeviceFields extends AbstractEntityFields implements ProfileAwareFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java index 067c961b9e..2331829054 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java @@ -16,6 +16,7 @@ package org.thingsboard.server.common.data.edqs.fields; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import org.thingsboard.server.common.data.DeviceProfileType; @@ -23,6 +24,7 @@ import org.thingsboard.server.common.data.DeviceProfileType; import java.util.UUID; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class DeviceProfileFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java index 1d257b06e1..e048eb22a8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class EdgeFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java index 4e326cf779..c5027dfc8f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class EntityViewFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java index 13e05daad4..5c5a139364 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java @@ -16,12 +16,14 @@ package org.thingsboard.server.common.data.edqs.fields; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import java.util.UUID; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class QueueStatsFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java index 25b7db6aaa..d580f6b913 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class RuleChainFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java index 9b538511b2..ba350fec54 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class TenantFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java index f6a2889f67..5d1ff0e0e2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java @@ -16,6 +16,7 @@ package org.thingsboard.server.common.data.edqs.fields; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; import org.thingsboard.server.common.data.id.TenantId; @@ -23,6 +24,7 @@ import org.thingsboard.server.common.data.id.TenantId; import java.util.UUID; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class TenantProfileFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java index 225b85680f..70fde8bf9c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java @@ -17,6 +17,7 @@ package org.thingsboard.server.common.data.edqs.fields; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data +@EqualsAndHashCode(callSuper = false) @NoArgsConstructor @SuperBuilder public class UserFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java index 233c53849c..f46339c15a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java @@ -16,8 +16,10 @@ package org.thingsboard.server.common.data.kv; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = false) public class BaseDeleteTsKvQuery extends BaseTsKvQuery implements DeleteTsKvQuery { private final Boolean rewriteLatestIfDeleted; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java index f9d2e8d3d8..1599413c1c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.query; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; @@ -30,6 +31,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Data +@EqualsAndHashCode(callSuper = false) @ToString public class AlarmCountQuery extends EntityCountQuery { private long startTs; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java b/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java index 57e0e6af66..d6a4f2b12f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.queue; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; @@ -30,6 +31,7 @@ import org.thingsboard.server.common.data.validation.NoXss; import java.util.Optional; @Data +@EqualsAndHashCode(callSuper = false) public class Queue extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, QueueConfig { private TenantId tenantId; @NoXss diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java index cb861a6726..0624350d7e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java @@ -16,12 +16,14 @@ package org.thingsboard.server.common.data.rule; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeStateId; @Data +@EqualsAndHashCode(callSuper = false) public class RuleNodeState extends BaseData { private RuleNodeId ruleNodeId; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java index 9fe846796b..9acce93aa3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.widget; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.validation.NoXss; @@ -26,6 +27,7 @@ import java.util.Collections; import java.util.List; @Data +@EqualsAndHashCode(callSuper = false) public class WidgetTypeInfo extends BaseWidgetType { @Serial diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java index 45d9e21e39..8356a17748 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java @@ -16,8 +16,10 @@ package org.thingsboard.server.transport.mqtt.limits; import lombok.Data; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = false) public class GatewaySessionLimits extends SessionLimits { private SessionRateLimits gatewayRateLimits; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java index 44a38bf445..421a22a9d2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java @@ -26,6 +26,7 @@ import jakarta.persistence.SqlResultSetMapping; import jakarta.persistence.SqlResultSetMappings; import jakarta.persistence.Table; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; import org.thingsboard.server.dao.sqlts.latest.SearchTsKvLatestRepository; @@ -35,6 +36,7 @@ import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.VERSION_COLUMN; @Data +@EqualsAndHashCode(callSuper = false) @Entity @Table(name = "ts_kv_latest") @IdClass(TsKvLatestCompositeKey.class) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java index a69a157241..ab305919fd 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java @@ -16,10 +16,12 @@ package org.thingsboard.rule.engine.action; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.server.common.data.script.ScriptLanguage; @Data +@EqualsAndHashCode(callSuper = false) public class TbClearAlarmNodeConfiguration extends TbAbstractAlarmNodeConfiguration implements NodeConfiguration { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java index 8c791e7634..bf305a55d1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.action; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.script.ScriptLanguage; @@ -25,6 +26,7 @@ import java.util.Collections; import java.util.List; @Data +@EqualsAndHashCode(callSuper = false) public class TbCreateAlarmNodeConfiguration extends TbAbstractAlarmNodeConfiguration implements NodeConfiguration { @NoXss diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java index 3b59d814f1..6551352823 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.geo; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.common.util.geo.PerimeterType; import java.util.concurrent.TimeUnit; @@ -24,6 +25,7 @@ import java.util.concurrent.TimeUnit; * Created by ashvayka on 19.01.18. */ @Data +@EqualsAndHashCode(callSuper = false) public class TbGpsGeofencingActionNodeConfiguration extends TbGpsGeofencingFilterNodeConfiguration { private int minInsideDuration; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java index fe17c659e1..93d1ef7ef8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java @@ -20,6 +20,7 @@ import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.thingsboard.common.util.AzureIotHubUtil; @@ -29,6 +30,7 @@ import org.thingsboard.rule.engine.credentials.CredentialsType; import java.security.Security; @Data +@EqualsAndHashCode(callSuper = false) @Slf4j @JsonIgnoreProperties(ignoreUnknown = true) public class AzureIotHubSasCredentials extends CertPemCredentials { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java index c786478575..f11173f3f9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java @@ -17,9 +17,11 @@ package org.thingsboard.rule.engine.mqtt.azure; import io.netty.handler.codec.mqtt.MqttVersion; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.rule.engine.mqtt.TbMqttNodeConfiguration; @Data +@EqualsAndHashCode(callSuper = false) public class TbAzureIotHubNodeConfiguration extends TbMqttNodeConfiguration { @Override From 3615de5d75a00afb3c23b7da977617e243c7d3c5 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Fri, 24 Apr 2026 11:31:54 +0200 Subject: [PATCH 12/59] chore(build): migrate deprecated DefaultedRedisConnection byte[] calls to typed command APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Routes get/set/del/scan/getSet/hGet/hSet/hDel/lRange/zRem/getRange calls through stringCommands()/keyCommands()/hashCommands()/listCommands()/ zSetCommands() instead of the deprecated shortcut methods on DefaultedRedisConnection. Behavior-preserving — Spring Data Redis delegates the deprecated overloads to these same typed commands. Eliminates 70 deprecation warnings across RedisOtaPackageDataCache, five Leshan-forked lwm2m stores (TbLwM2mRedisRegistrationStore, TbLwM2mRedisSecurityStore, TbRedisLwM2MClientStore, TbRedisLwM2MModelConfigStore, TbLwM2mRedisClientOtaInfoStore, TbLwM2MDtlsSessionRedisStore) and the TbRedisLwM2MClientStoreTest unit test, which now uses Answers.RETURNS_DEEP_STUBS to mock the typed command chain. Part of #15481 Tier 3 cleanup. --- .../cache/ota/RedisOtaPackageDataCache.java | 8 +-- .../store/TbLwM2MDtlsSessionRedisStore.java | 6 +- .../store/TbLwM2mRedisClientOtaInfoStore.java | 4 +- .../store/TbLwM2mRedisRegistrationStore.java | 66 +++++++++---------- .../store/TbLwM2mRedisSecurityStore.java | 24 +++---- .../server/store/TbRedisLwM2MClientStore.java | 10 +-- .../store/TbRedisLwM2MModelConfigStore.java | 8 +-- .../store/TbRedisLwM2MClientStoreTest.java | 21 +++--- 8 files changed, 74 insertions(+), 73 deletions(-) diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java index c3a9ff0385..1e13b1cfe9 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/ota/RedisOtaPackageDataCache.java @@ -39,26 +39,26 @@ public class RedisOtaPackageDataCache implements OtaPackageDataCache { public byte[] get(String key, int chunkSize, int chunk) { try (RedisConnection connection = redisConnectionFactory.getConnection()) { if (chunkSize == 0) { - return connection.get(toOtaPackageCacheKey(key)); + return connection.stringCommands().get(toOtaPackageCacheKey(key)); } int startIndex = chunkSize * chunk; int endIndex = startIndex + chunkSize - 1; - return connection.getRange(toOtaPackageCacheKey(key), startIndex, endIndex); + return connection.stringCommands().getRange(toOtaPackageCacheKey(key), startIndex, endIndex); } } @Override public void put(String key, byte[] value) { try (RedisConnection connection = redisConnectionFactory.getConnection()) { - connection.set(toOtaPackageCacheKey(key), value); + connection.stringCommands().set(toOtaPackageCacheKey(key), value); } } @Override public void evict(String key) { try (RedisConnection connection = redisConnectionFactory.getConnection()) { - connection.del(toOtaPackageCacheKey(key)); + connection.keyCommands().del(toOtaPackageCacheKey(key)); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java index ead9269108..fa78bbb7bb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java @@ -33,7 +33,7 @@ public class TbLwM2MDtlsSessionRedisStore implements TbLwM2MDtlsSessionStore { try (var c = connectionFactory.getConnection()) { var serializedMsg = JavaSerDesUtil.encode(msg); if (serializedMsg != null) { - c.set(getKey(endpoint), serializedMsg); + c.stringCommands().set(getKey(endpoint), serializedMsg); } else { throw new RuntimeException("Problem with serialization of message: " + msg); } @@ -43,7 +43,7 @@ public class TbLwM2MDtlsSessionRedisStore implements TbLwM2MDtlsSessionStore { @Override public TbX509DtlsSessionInfo get(String endpoint) { try (var c = connectionFactory.getConnection()) { - var data = c.get(getKey(endpoint)); + var data = c.stringCommands().get(getKey(endpoint)); if (data != null) { return JavaSerDesUtil.decode(data); } else { @@ -55,7 +55,7 @@ public class TbLwM2MDtlsSessionRedisStore implements TbLwM2MDtlsSessionStore { @Override public void remove(String endpoint) { try (var c = connectionFactory.getConnection()) { - c.del(getKey(endpoint)); + c.keyCommands().del(getKey(endpoint)); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisClientOtaInfoStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisClientOtaInfoStore.java index 8301d4a448..c75a5ff8a0 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisClientOtaInfoStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisClientOtaInfoStore.java @@ -33,7 +33,7 @@ public class TbLwM2mRedisClientOtaInfoStore implements TbLwM2MClientOtaInfoStore private void put(OtaPackageType type, LwM2MClientOtaInfo info) { try (var connection = connectionFactory.getConnection()) { - connection.set((OTA_EP + type + info.getEndpoint()).getBytes(), JacksonUtil.toString(info).getBytes()); + connection.stringCommands().set((OTA_EP + type + info.getEndpoint()).getBytes(), JacksonUtil.toString(info).getBytes()); } } @@ -59,7 +59,7 @@ public class TbLwM2mRedisClientOtaInfoStore implements TbLwM2MClientOtaInfoStore private > T getLwM2MClientOtaInfo(OtaPackageType type, String endpoint, Class clazz) { try (var connection = connectionFactory.getConnection()) { - byte[] data = connection.get((OTA_EP + type + endpoint).getBytes()); + byte[] data = connection.stringCommands().get((OTA_EP + type + endpoint).getBytes()); return JacksonUtil.fromBytes(data, clazz); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java index 8158e82a81..5937383156 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java @@ -163,15 +163,15 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab lock.lock(); // add registration byte[] k = toEndpointKey(registration.getEndpoint()); - byte[] old = connection.getSet(k, serializeReg(registration)); + byte[] old = connection.stringCommands().getSet(k, serializeReg(registration)); // add registration: secondary indexes byte[] regid_idx = toRegIdKey(registration.getId()); - connection.set(regid_idx, registration.getEndpoint().getBytes(UTF_8)); + connection.stringCommands().set(regid_idx, registration.getEndpoint().getBytes(UTF_8)); byte[] addr_idx = toRegAddrKey(registration.getSocketAddress()); - connection.set(addr_idx, registration.getEndpoint().getBytes(UTF_8)); + connection.stringCommands().set(addr_idx, registration.getEndpoint().getBytes(UTF_8)); byte[] identity_idx = toRegIdentityKey(registration.getClientTransportData().getIdentity()); - connection.set(identity_idx, registration.getEndpoint().getBytes(UTF_8)); + connection.stringCommands().set(identity_idx, registration.getEndpoint().getBytes(UTF_8)); // Add or update expiration addOrUpdateExpiration(connection, registration); @@ -180,7 +180,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab Registration oldRegistration = deserializeReg(old); // remove old secondary index if (!registration.getId().equals(oldRegistration.getId())) - connection.del(toRegIdKey(oldRegistration.getId())); + connection.keyCommands().del(toRegIdKey(oldRegistration.getId())); if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) { removeAddrIndex(connection, oldRegistration); } @@ -209,7 +209,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab try (var connection = connectionFactory.getConnection()) { // Fetch the registration ep by registration ID index - byte[] ep = connection.get(toRegIdKey(update.getRegistrationId())); + byte[] ep = connection.stringCommands().get(toRegIdKey(update.getRegistrationId())); if (ep == null) { return null; } @@ -220,7 +220,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab lock.lock(); // Fetch the registration - byte[] data = connection.get(toEndpointKey(ep)); + byte[] data = connection.stringCommands().get(toEndpointKey(ep)); if (data == null) { return null; } @@ -230,7 +230,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab Registration updatedRegistration = update.update(r); // Store the new registration - connection.set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration)); + connection.stringCommands().set(toEndpointKey(updatedRegistration.getEndpoint()), serializeReg(updatedRegistration)); // Add or update expiration addOrUpdateExpiration(connection, updatedRegistration); @@ -239,7 +239,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab * If registration is already associated to this address we don't care as we only want to keep the most * recent binding. */ byte[] addr_idx = toRegAddrKey(updatedRegistration.getSocketAddress()); - connection.set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8)); + connection.stringCommands().set(addr_idx, updatedRegistration.getEndpoint().getBytes(UTF_8)); if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) { removeAddrIndex(connection, r); } @@ -265,11 +265,11 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab } private Registration getRegistration(RedisConnection connection, String registrationId) { - byte[] ep = connection.get(toRegIdKey(registrationId)); + byte[] ep = connection.stringCommands().get(toRegIdKey(registrationId)); if (ep == null) { return null; } - byte[] data = connection.get(toEndpointKey(ep)); + byte[] data = connection.stringCommands().get(toEndpointKey(ep)); if (data == null) { return null; } @@ -281,7 +281,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab public Registration getRegistrationByEndpoint(String endpoint) { Validate.notNull(endpoint); try (var connection = connectionFactory.getConnection()) { - byte[] data = connection.get(toEndpointKey(endpoint)); + byte[] data = connection.stringCommands().get(toEndpointKey(endpoint)); if (data == null) { return null; } @@ -293,11 +293,11 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab public Registration getRegistrationByAdress(InetSocketAddress address) { Validate.notNull(address); try (var connection = connectionFactory.getConnection()) { - byte[] ep = connection.get(toRegAddrKey(address)); + byte[] ep = connection.stringCommands().get(toRegAddrKey(address)); if (ep == null) { return null; } - byte[] data = connection.get(toEndpointKey(ep)); + byte[] data = connection.stringCommands().get(toEndpointKey(ep)); if (data == null) { return null; } @@ -309,11 +309,11 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab public Registration getRegistrationByIdentity(LwM2mIdentity identity) { Validate.notNull(identity); try (var connection = connectionFactory.getConnection()) { - byte[] ep = connection.get(toRegIdentityKey(identity)); + byte[] ep = connection.stringCommands().get(toRegIdentityKey(identity)); if (ep == null) { return null; } - byte[] data = connection.get(toEndpointKey(ep)); + byte[] data = connection.stringCommands().get(toEndpointKey(ep)); if (data == null) { return null; } @@ -332,12 +332,12 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab clusterConnection.clusterGetNodes().forEach(node -> scans.add(clusterConnection.scan(node, scanOptions))); } else { - scans.add(scanConnection.scan(scanOptions)); + scans.add(scanConnection.keyCommands().scan(scanOptions)); } scans.forEach(scan -> { scan.forEachRemaining(key -> { - byte[] element = getConnection.get(key); + byte[] element = getConnection.stringCommands().get(key); if (element != null) { list.add(deserializeReg(element)); } @@ -357,7 +357,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab private Deregistration removeRegistration(RedisConnection connection, String registrationId, boolean removeOnlyIfNotAlive) { // fetch the client ep by registration ID index - byte[] ep = connection.get(toRegIdKey(registrationId)); + byte[] ep = connection.stringCommands().get(toRegIdKey(registrationId)); if (ep == null) { return null; } @@ -369,16 +369,16 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab lock.lock(); // fetch the client - byte[] data = connection.get(toEndpointKey(ep)); + byte[] data = connection.stringCommands().get(toEndpointKey(ep)); if (data == null) { return null; } Registration r = deserializeReg(data); if (!removeOnlyIfNotAlive || !r.isAlive(gracePeriod)) { - long nbRemoved = connection.del(toRegIdKey(r.getId())); + long nbRemoved = connection.keyCommands().del(toRegIdKey(r.getId())); if (nbRemoved > 0) { - connection.del(toEndpointKey(r.getEndpoint())); + connection.keyCommands().del(toEndpointKey(r.getEndpoint())); Collection obsRemoved = unsafeRemoveAllObservations(connection, r.getId()); removeAddrIndex(connection, r); removeIdentityIndex(connection, r); @@ -407,12 +407,12 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab // Watch the key to remove. // connection.watch(indexKey); - byte[] epFromAddr = connection.get(indexKey); + byte[] epFromAddr = connection.stringCommands().get(indexKey); // Delete the key if needed. if (Arrays.equals(epFromAddr, endpointName.getBytes(UTF_8))) { // Try to delete the key // connection.multi(); - connection.del(indexKey); + connection.keyCommands().del(indexKey); // connection.exec(); // if transaction failed this is not an issue as the index is probably reused and we don't need to // delete it anymore. @@ -427,7 +427,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab } private void removeExpiration(RedisConnection connection, Registration registration) { - connection.zRem(EXP_EP, registration.getEndpoint().getBytes(UTF_8)); + connection.zSetCommands().zRem(EXP_EP, registration.getEndpoint().getBytes(UTF_8)); } private byte[] toRegIdKey(String registrationId) { @@ -556,7 +556,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab @Override public Observation getObservation(ObservationIdentifier observationId) { try (var connection = connectionFactory.getConnection()) { - byte[] observationValue = connection.get(toKey(OBS_TKN, observationId.getBytes())); + byte[] observationValue = connection.stringCommands().get(toKey(OBS_TKN, observationId.getBytes())); return deserializeObs(observationValue); } } @@ -570,7 +570,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab try (var connection = connectionFactory.getConnection()) { // fetch the client ep by registration ID index - byte[] ep = connection.get(toRegIdKey(registrationId)); + byte[] ep = connection.stringCommands().get(toRegIdKey(registrationId)); if (ep == null) { return null; } @@ -635,7 +635,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab public Observation get(Token token) { try (var connection = connectionFactory.getConnection()) { - byte[] obs = connection.get(toKey(OBS_TKN, token.getBytes())); + byte[] obs = connection.stringCommands().get(toKey(OBS_TKN, token.getBytes())); if (obs == null) { return null; } else { @@ -664,14 +664,14 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab byte[] regIdKey = toKey(OBS_TKNS_REGID_IDX, registrationId); // fetch all observations by token - for (byte[] token : connection.lRange(regIdKey, 0, -1)) { - byte[] obs = connection.get(toKey(OBS_TKN, token)); + for (byte[] token : connection.listCommands().lRange(regIdKey, 0, -1)) { + byte[] obs = connection.stringCommands().get(toKey(OBS_TKN, token)); if (obs != null) { removed.add(deserializeObs(obs)); } - connection.del(toKey(OBS_TKN, token)); + connection.keyCommands().del(toKey(OBS_TKN, token)); } - connection.del(regIdKey); + connection.keyCommands().del(regIdKey); return removed; } @@ -752,7 +752,7 @@ public class TbLwM2mRedisRegistrationStore implements RegistrationStore, Startab System.currentTimeMillis(), 0, cleanLimit); for (byte[] endpoint : endpointsExpired) { - byte[] data = connection.get(toEndpointKey(endpoint)); + byte[] data = connection.stringCommands().get(toEndpointKey(endpoint)); if (data != null && data.length > 0) { Registration r = deserializeReg(data); if (!r.isAlive(gracePeriod)) { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java index b07156d0ef..1e5d480c81 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java @@ -52,7 +52,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { try (var connection = connectionFactory.getConnection()) { lock = redisLock.obtain(toLockKey(endpoint)); lock.lock(); - byte[] data = connection.get((SEC_EP + endpoint).getBytes()); + byte[] data = connection.stringCommands().get((SEC_EP + endpoint).getBytes()); if (data == null || data.length == 0) { return null; } else { @@ -96,11 +96,11 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { try (var connection = connectionFactory.getConnection()) { lock = redisLock.obtain(toLockKey(identity)); lock.lock(); - byte[] ep = connection.hGet(PSKID_SEC.getBytes(), identity.getBytes()); + byte[] ep = connection.hashCommands().hGet(PSKID_SEC.getBytes(), identity.getBytes()); if (ep == null) { return null; } else { - byte[] data = connection.get((SEC_EP + new String(ep)).getBytes()); + byte[] data = connection.stringCommands().get((SEC_EP + new String(ep)).getBytes()); if (data == null || data.length == 0) { return null; } else { @@ -128,17 +128,17 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { lock = redisLock.obtain(tbSecurityInfo.getEndpoint()); lock.lock(); if (info != null && info.getPskIdentity() != null) { - byte[] oldEndpointBytes = connection.hGet(PSKID_SEC.getBytes(), info.getPskIdentity().getBytes()); + byte[] oldEndpointBytes = connection.hashCommands().hGet(PSKID_SEC.getBytes(), info.getPskIdentity().getBytes()); if (oldEndpointBytes != null) { String oldEndpoint = new String(oldEndpointBytes); if (!oldEndpoint.equals(info.getEndpoint())) { throw new NonUniqueSecurityInfoException("PSK Identity " + info.getPskIdentity() + " is already used"); } - connection.hSet(PSKID_SEC.getBytes(), info.getPskIdentity().getBytes(), info.getEndpoint().getBytes()); + connection.hashCommands().hSet(PSKID_SEC.getBytes(), info.getPskIdentity().getBytes(), info.getEndpoint().getBytes()); } } - byte[] previousData = connection.getSet((SEC_EP + tbSecurityInfo.getEndpoint()).getBytes(), tbSecurityInfoSerialized); + byte[] previousData = connection.stringCommands().getSet((SEC_EP + tbSecurityInfo.getEndpoint()).getBytes(), tbSecurityInfoSerialized); // for tests: redis connect NoSec (securityInfo == null) log.info("lwm2m redis connect. Endpoint: [{}], secMode: [{}] key: [{}], tbSecurityInfoSerialized [{}]", @@ -147,7 +147,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { if (previousData != null && info != null) { String previousIdentity = ((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(previousData)).getSecurityInfo().getPskIdentity(); if (previousIdentity != null && !previousIdentity.equals(info.getPskIdentity())) { - connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes()); + connection.hashCommands().hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes()); } } } finally { @@ -163,7 +163,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { try (var connection = connectionFactory.getConnection()) { lock = redisLock.obtain(endpoint); lock.lock(); - byte[] data = connection.get((SEC_EP + endpoint).getBytes()); + byte[] data = connection.stringCommands().get((SEC_EP + endpoint).getBytes()); if (data != null && data.length > 0) { return JavaSerDesUtil.decode(data); } else { @@ -182,13 +182,13 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { try (var connection = connectionFactory.getConnection()) { lock = redisLock.obtain(endpoint); lock.lock(); - byte[] data = connection.get((SEC_EP + endpoint).getBytes()); + byte[] data = connection.stringCommands().get((SEC_EP + endpoint).getBytes()); if (data != null && data.length > 0) { SecurityInfo info = ((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(data)).getSecurityInfo(); if (info != null && info.getPskIdentity() != null) { - connection.hDel(PSKID_SEC.getBytes(), info.getPskIdentity().getBytes()); + connection.hashCommands().hDel(PSKID_SEC.getBytes(), info.getPskIdentity().getBytes()); } - connection.del((SEC_EP + endpoint).getBytes()); + connection.keyCommands().del((SEC_EP + endpoint).getBytes()); } } finally { if (lock != null) { @@ -203,7 +203,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { private SecurityMode getSecurityModeByRegistration (RedisConnection connection, String endpoint) { try { - byte[] data = connection.get((REG_EP + endpoint).getBytes()); + byte[] data = connection.stringCommands().get((REG_EP + endpoint).getBytes()); JsonNode registrationNode = JacksonUtil.fromString(new String(data != null ? data : new byte[0]), JsonNode.class); String typeModeStr = registrationNode.get("transportdata").get("identity").get("type").asText(); return "unsecure".equals(typeModeStr) ? SecurityMode.NO_SEC : null; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStore.java index 4beefb4896..73d4bd95da 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStore.java @@ -45,7 +45,7 @@ public class TbRedisLwM2MClientStore implements TbLwM2MClientStore { @Override public LwM2mClient get(String endpoint) { try (var connection = connectionFactory.getConnection()) { - byte[] data = connection.get(getKey(endpoint)); + byte[] data = connection.stringCommands().get(getKey(endpoint)); if (data == null) { return null; } else { @@ -70,12 +70,12 @@ public class TbRedisLwM2MClientStore implements TbLwM2MClientStore { clusterConnection.clusterGetNodes().forEach(node -> scans.add(clusterConnection.scan(node, scanOptions))); } else { - scans.add(scanConnection.scan(scanOptions)); + scans.add(scanConnection.keyCommands().scan(scanOptions)); } scans.forEach(scan -> { scan.forEachRemaining(key -> { - byte[] element = getConnection.get(key); + byte[] element = getConnection.stringCommands().get(key); if (element != null) { try { clients.add(deserialize(element)); @@ -97,7 +97,7 @@ public class TbRedisLwM2MClientStore implements TbLwM2MClientStore { try { byte[] clientSerialized = serialize(client); try (var connection = connectionFactory.getConnection()) { - connection.getSet(getKey(client.getEndpoint()), clientSerialized); + connection.stringCommands().getSet(getKey(client.getEndpoint()), clientSerialized); } } catch (Exception e) { log.warn("Failed to serialize client: {}", client, e); @@ -108,7 +108,7 @@ public class TbRedisLwM2MClientStore implements TbLwM2MClientStore { @Override public void remove(String endpoint) { try (var connection = connectionFactory.getConnection()) { - connection.del(getKey(endpoint)); + connection.keyCommands().del(getKey(endpoint)); } } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MModelConfigStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MModelConfigStore.java index 31a78234d0..65ed90d15d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MModelConfigStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MModelConfigStore.java @@ -44,12 +44,12 @@ public class TbRedisLwM2MModelConfigStore implements TbLwM2MModelConfigStore { clusterConnection.clusterGetNodes().forEach(node -> scans.add(clusterConnection.scan(node, scanOptions))); } else { - scans.add(scanConnection.scan(scanOptions)); + scans.add(scanConnection.keyCommands().scan(scanOptions)); } scans.forEach(scan -> { scan.forEachRemaining(key -> { - byte[] element = getConnection.get(key); + byte[] element = getConnection.stringCommands().get(key); if (element != null) { configs.add(JacksonUtil.fromBytes(element, LwM2MModelConfig.class)); } @@ -63,14 +63,14 @@ public class TbRedisLwM2MModelConfigStore implements TbLwM2MModelConfigStore { public void put(LwM2MModelConfig modelConfig) { byte[] clientSerialized = JacksonUtil.writeValueAsBytes(modelConfig); try (var connection = connectionFactory.getConnection()) { - connection.getSet(getKey(modelConfig.getEndpoint()), clientSerialized); + connection.stringCommands().getSet(getKey(modelConfig.getEndpoint()), clientSerialized); } } @Override public void remove(String endpoint) { try (var connection = connectionFactory.getConnection()) { - connection.del(getKey(endpoint)); + connection.keyCommands().del(getKey(endpoint)); } } diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStoreTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStoreTest.java index 9fe29c1188..fe8d66365f 100644 --- a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStoreTest.java +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbRedisLwM2MClientStoreTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.lwm2m.server.store; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.redis.connection.RedisConnection; @@ -51,10 +52,10 @@ class TbRedisLwM2MClientStoreTest { @Mock RedisConnectionFactory connectionFactory; - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) RedisConnection scanConnection; - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) RedisConnection getConnection; TbRedisLwM2MClientStore store; @@ -77,8 +78,8 @@ class TbRedisLwM2MClientStoreTest { // Cursor created before thenReturn to avoid Mockito unfinished-stubbing error Cursor cursor = cursorOf(key); - when(scanConnection.scan(any(ScanOptions.class))).thenReturn(cursor); - when(getConnection.get(key)).thenReturn(value); + when(scanConnection.keyCommands().scan(any(ScanOptions.class))).thenReturn(cursor); + when(getConnection.stringCommands().get(key)).thenReturn(value); Set result = store.getAll(); @@ -89,29 +90,29 @@ class TbRedisLwM2MClientStoreTest { @Test void getAll_getIsNeverCalledOnScanConnection() { Cursor cursor = cursorOf(); - when(scanConnection.scan(any(ScanOptions.class))).thenReturn(cursor); + when(scanConnection.keyCommands().scan(any(ScanOptions.class))).thenReturn(cursor); store.getAll(); - verify(scanConnection, never()).get(any(byte[].class)); + verify(scanConnection.stringCommands(), never()).get(any(byte[].class)); } @Test void getAll_scanIsNeverCalledOnGetConnection() { Cursor cursor = cursorOf(); - when(scanConnection.scan(any(ScanOptions.class))).thenReturn(cursor); + when(scanConnection.keyCommands().scan(any(ScanOptions.class))).thenReturn(cursor); store.getAll(); - verify(getConnection, never()).scan(any(ScanOptions.class)); + verify(getConnection.keyCommands(), never()).scan(any(ScanOptions.class)); } @Test void getAll_skipsKeyWhenValueIsNull() { byte[] key = "CLIENT#EP#gone".getBytes(); Cursor cursor = cursorOf(key); - when(scanConnection.scan(any(ScanOptions.class))).thenReturn(cursor); - // getConnection.get(key) returns null by default — no stubbing needed + when(scanConnection.keyCommands().scan(any(ScanOptions.class))).thenReturn(cursor); + // getConnection.stringCommands().get(key) returns null by default — no stubbing needed Set result = store.getAll(); From 0340612e091efeea50b63a20528014f516296174 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Fri, 24 Apr 2026 15:00:26 +0200 Subject: [PATCH 13/59] chore(hygiene): replaced 24 deprecated commons-lang3 API calls on lts-4.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RandomStringUtils.randomAlphanumeric/Alphabetic/Numeric/random → secure().nextX (10) - RandomUtils.nextInt/nextBytes → secure().randomX (3) - NumberUtils.isNumber → isCreatable (2) - StringUtils.equals → Objects.equals where both args are String (3) - StringUtils.removeStart → common.data.StringUtils.removeStart wrapper (6) --- .../install/DefaultSystemDataLoaderService.java | 2 +- .../auth/mfa/provider/impl/TotpTwoFaProvider.java | 2 +- .../server/service/ws/WebSocketSessionType.java | 4 ++-- .../server/controller/AbstractWebTest.java | 2 +- .../notification/AbstractNotificationApiTest.java | 2 +- .../notification/NotificationApiWsClient.java | 2 +- .../thingsboard/server/common/data/EntityType.java | 4 +++- .../thingsboard/server/common/data/StringUtils.java | 13 +++++++------ .../server/common/data/util/TemplateUtils.java | 2 +- .../server/common/data/util/TypeCastUtil.java | 2 +- .../server/service/sync/vc/GitRepository.java | 5 +++-- .../server/dao/resource/BaseImageService.java | 2 +- .../server/dao/resource/BaseResourceService.java | 8 +++++--- .../org/thingsboard/monitoring/client/WsClient.java | 2 +- .../monitoring/service/MonitoringEntityService.java | 2 +- .../client/tools/migrator/PgCaMigrator.java | 2 +- 16 files changed, 31 insertions(+), 25 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index 4864f53e17..9b921699f9 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -330,7 +330,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { private String generateRandomKey() { return Base64.getEncoder().encodeToString( - RandomStringUtils.randomAlphanumeric(64).getBytes(StandardCharsets.UTF_8)); + RandomStringUtils.secure().nextAlphanumeric(64).getBytes(StandardCharsets.UTF_8)); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/provider/impl/TotpTwoFaProvider.java b/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/provider/impl/TotpTwoFaProvider.java index 23eda67a77..a7fbdb84e4 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/provider/impl/TotpTwoFaProvider.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/mfa/provider/impl/TotpTwoFaProvider.java @@ -62,7 +62,7 @@ public class TotpTwoFaProvider implements TwoFaProvider forName(String name) { return Arrays.stream(values()) - .filter(sessionType -> StringUtils.equals(sessionType.name, name)) + .filter(sessionType -> Objects.equals(sessionType.name, name)) .findFirst(); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index bbf3a3467e..4f8ed55731 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -1223,7 +1223,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { protected NotificationTarget createNotificationTarget(UsersFilter usersFilter) { NotificationTarget notificationTarget = new NotificationTarget(); - notificationTarget.setName(usersFilter.toString() + RandomStringUtils.randomNumeric(5)); + notificationTarget.setName(usersFilter.toString() + RandomStringUtils.secure().nextNumeric(5)); PlatformUsersNotificationTargetConfig targetConfig = new PlatformUsersNotificationTargetConfig(); targetConfig.setUsersFilter(usersFilter); notificationTarget.setConfiguration(targetConfig); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java index f5607415fa..65a7e2b4fa 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java @@ -155,7 +155,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest User user = new User(); user.setTenantId(tenantId); user.setAuthority(authority); - user.setEmail(RandomStringUtils.randomAlphabetic(20) + "@thingsboard.com"); + user.setEmail(RandomStringUtils.secure().nextAlphabetic(20) + "@thingsboard.com"); user = createUserAndLogin(user, "12345678"); NotificationApiWsClient wsClient = buildAndConnectWebSocketClient(); return Pair.of(user, wsClient); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java index b538972dd7..f6d94f5170 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiWsClient.java @@ -131,7 +131,7 @@ public class NotificationApiWsClient extends TbTestWebSocketClient { } private int newCmdId() { - return RandomUtils.nextInt(1, 1000); + return RandomUtils.secure().randomInt(1, 1000); } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index a95208e457..7eef085340 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -22,6 +22,8 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; +import static org.thingsboard.server.common.data.StringUtils.removeStart; + public enum EntityType { TENANT(1), CUSTOMER(2), @@ -76,7 +78,7 @@ public enum EntityType { @Getter private final String tableName; @Getter - private final String normalName = StringUtils.capitalize(StringUtils.removeStart(name(), "TB_") + private final String normalName = StringUtils.capitalize(removeStart(name(), "TB_") .toLowerCase().replaceAll("_", " ")); public static final List NORMAL_NAMES = EnumSet.allOf(EntityType.class).stream() diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index 37242dfa1d..59977264b6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.List; +import java.util.Objects; import java.util.function.Function; import static org.apache.commons.lang3.StringUtils.repeat; @@ -155,7 +156,7 @@ public class StringUtils { } public static boolean equals(String str1, String str2) { - return org.apache.commons.lang3.StringUtils.equals(str1, str2); + return Objects.equals(str1, str2); } public static boolean equalsAny(String string, String... otherStrings) { @@ -210,23 +211,23 @@ public class StringUtils { } public static String randomNumeric(int length) { - return RandomStringUtils.randomNumeric(length); + return RandomStringUtils.secure().nextNumeric(length); } public static String random(int length) { - return RandomStringUtils.random(length); + return RandomStringUtils.secure().next(length); } public static String random(int length, String chars) { - return RandomStringUtils.random(length, chars); + return RandomStringUtils.secure().next(length, chars); } public static String randomAlphanumeric(int count) { - return RandomStringUtils.randomAlphanumeric(count); + return RandomStringUtils.secure().nextAlphanumeric(count); } public static String randomAlphabetic(int count) { - return RandomStringUtils.randomAlphabetic(count); + return RandomStringUtils.secure().nextAlphabetic(count); } public static String generateSafeToken(int length) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/util/TemplateUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/util/TemplateUtils.java index beaec13748..d740a065ce 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/util/TemplateUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/util/TemplateUtils.java @@ -23,7 +23,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.google.common.base.Strings.nullToEmpty; -import static org.apache.commons.lang3.StringUtils.removeStart; +import static org.thingsboard.server.common.data.StringUtils.removeStart; public class TemplateUtils { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/util/TypeCastUtil.java b/common/data/src/main/java/org/thingsboard/server/common/data/util/TypeCastUtil.java index 78ff4b0eba..887cedefa4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/util/TypeCastUtil.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/util/TypeCastUtil.java @@ -63,7 +63,7 @@ public class TypeCastUtil { } private static boolean isNumber(String value) { - return NumberUtils.isNumber(value.replace(',', '.')); + return NumberUtils.isCreatable(value.replace(',', '.')); } private static boolean isSimpleDouble(String valueAsString) { diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java index 3602dd55ca..15dd615111 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java @@ -99,6 +99,7 @@ import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_NODELET import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD; import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_OTHER_REASON; import static org.eclipse.jgit.transport.RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED; +import static org.thingsboard.server.common.data.StringUtils.removeStart; @Slf4j public class GitRepository { @@ -448,7 +449,7 @@ public class GitRepository { private BranchInfo toBranchInfo(Ref ref) { String name = org.eclipse.jgit.lib.Repository.shortenRefName(ref.getName()); - String branchName = StringUtils.removeStart(name, "origin/"); + String branchName = removeStart(name, "origin/"); boolean isDefault = this.headId != null && this.headId.equals(ref.getObjectId()); return new BranchInfo(branchName, isDefault); } @@ -465,7 +466,7 @@ public class GitRepository { private ObjectId resolve(String rev) throws IOException { if (settings.isLocalOnly()) { - rev = StringUtils.removeStart(rev, "origin/"); + rev = removeStart(rev, "origin/"); } ObjectId result = git.getRepository().resolve(rev); if (result == null) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java index 11bbe797cf..18023f653c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java @@ -173,7 +173,7 @@ public class BaseImageService extends BaseResourceService implements ImageServic } private String generatePublicResourceKey() { - return RandomStringUtils.randomAlphanumeric(32); + return RandomStringUtils.secure().nextAlphanumeric(32); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java index 40b5a9778b..9af324e7ec 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseResourceService.java @@ -74,6 +74,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -82,6 +83,7 @@ import java.util.function.UnaryOperator; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.thingsboard.server.common.data.StringUtils.isNotEmpty; +import static org.thingsboard.server.common.data.StringUtils.removeStart; import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -588,7 +590,7 @@ public class BaseResourceService extends AbstractCachedEntityService devices, List keys) { EntityDataCmd cmd = new EntityDataCmd(); - cmd.setCmdId(RandomUtils.nextInt(0, 1000)); + cmd.setCmdId(RandomUtils.secure().randomInt(0, 1000)); EntityListFilter devicesFilter = new EntityListFilter(); devicesFilter.setEntityType(EntityType.DEVICE); diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java b/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java index 57fd7d280d..d85c0d3cc0 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/service/MonitoringEntityService.java @@ -162,7 +162,7 @@ public class MonitoringEntityService { device.setName(deviceName); DeviceCredentials credentials = new DeviceCredentials(); - credentials.setCredentialsId(RandomStringUtils.randomAlphabetic(20)); + credentials.setCredentialsId(RandomStringUtils.secure().nextAlphabetic(20)); DeviceData deviceData = new DeviceData(); deviceData.setConfiguration(new DefaultDeviceConfiguration()); diff --git a/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java b/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java index b88012c00e..2ef202dc9f 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java +++ b/tools/src/main/java/org/thingsboard/client/tools/migrator/PgCaMigrator.java @@ -249,7 +249,7 @@ public class PgCaMigrator { private List castToNumericIfPossible(List values) { try { - if (values.get(6) != null && NumberUtils.isNumber(values.get(6).toString())) { + if (values.get(6) != null && NumberUtils.isCreatable(values.get(6).toString())) { Double casted = NumberUtils.createDouble(values.get(6).toString()); List numeric = Lists.newArrayList(); numeric.addAll(values); From 6d125f57e92f86a9fd6285617b924873e004d92d Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Fri, 24 Apr 2026 23:18:47 +0200 Subject: [PATCH 14/59] Replaced 23 deprecated TenantId(UUID) constructor calls with TenantId.fromUUID on lts-4.2 --- .../transport/mqtt/session/GatewaySessionHandlerTest.java | 2 +- .../dao/sql/cf/DefaultNativeCalculatedFieldRepository.java | 2 +- .../thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java | 2 +- .../rule/engine/action/TbAssignToCustomerNodeTest.java | 2 +- .../rule/engine/action/TbCreateRelationNodeTest.java | 2 +- .../rule/engine/action/TbDeleteRelationNodeTest.java | 2 +- .../rule/engine/action/TbUnassignFromCustomerNodeTest.java | 2 +- .../rule/engine/filter/TbAssetTypeSwitchNodeTest.java | 2 +- .../rule/engine/filter/TbCheckAlarmStatusNodeTest.java | 2 +- .../rule/engine/filter/TbCheckRelationNodeTest.java | 2 +- .../rule/engine/filter/TbDeviceTypeSwitchNodeTest.java | 2 +- .../rule/engine/flow/TbRuleChainInputNodeTest.java | 2 +- .../rule/engine/metadata/TbGetCustomerDetailsNodeTest.java | 2 +- .../rule/engine/metadata/TbGetDeviceAttrNodeTest.java | 2 +- .../rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java | 2 +- .../rule/engine/metadata/TbGetRelatedAttributeNodeTest.java | 4 ++-- .../rule/engine/metadata/TbGetTenantAttributeNodeTest.java | 2 +- .../rule/engine/metadata/TbGetTenantDetailsNodeTest.java | 2 +- .../rule/engine/util/EntitiesFieldsAsyncLoaderTest.java | 4 ++-- .../engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java | 2 +- .../engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java | 2 +- 21 files changed, 23 insertions(+), 23 deletions(-) diff --git a/common/transport/mqtt/src/test/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandlerTest.java b/common/transport/mqtt/src/test/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandlerTest.java index 6b4e5e9925..30dc825a9b 100644 --- a/common/transport/mqtt/src/test/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandlerTest.java +++ b/common/transport/mqtt/src/test/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandlerTest.java @@ -75,7 +75,7 @@ public class GatewaySessionHandlerTest { ConcurrentHashMap devices = new ConcurrentHashMap<>(); TransportDeviceInfo deviceInfo = new TransportDeviceInfo(); deviceInfo.setDeviceId(new DeviceId(UUID.randomUUID())); - deviceInfo.setTenantId(new TenantId(UUID.randomUUID())); + deviceInfo.setTenantId(TenantId.fromUUID(UUID.randomUUID())); deviceInfo.setCustomerId(new CustomerId(UUID.randomUUID())); deviceInfo.setDeviceName("device1"); deviceInfo.setDeviceType("default"); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java index 9734af7d7a..4cce4c5041 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/cf/DefaultNativeCalculatedFieldRepository.java @@ -126,7 +126,7 @@ public class DefaultNativeCalculatedFieldRepository implements NativeCalculatedF CalculatedFieldLink calculatedFieldLink = new CalculatedFieldLink(); calculatedFieldLink.setId(new CalculatedFieldLinkId(id)); calculatedFieldLink.setCreatedTime(createdTime); - calculatedFieldLink.setTenantId(new TenantId(tenantId)); + calculatedFieldLink.setTenantId(TenantId.fromUUID(tenantId)); calculatedFieldLink.setEntityId(EntityIdFactory.getByTypeAndUuid(entityType, entityId)); calculatedFieldLink.setCalculatedFieldId(new CalculatedFieldId(calculatedFieldId)); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java index 3ddf318e2f..e03b161692 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java @@ -132,7 +132,7 @@ public class JpaBaseEventDaoTest extends AbstractJpaDaoTest { StatisticsEvent.StatisticsEventBuilder event = StatisticsEvent.builder(); event.id(eventId); event.ts(System.currentTimeMillis()); - event.tenantId(new TenantId(tenantId)); + event.tenantId(TenantId.fromUUID(tenantId)); event.entityId(entityId); event.serviceId("server A"); event.messagesProcessed(1); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNodeTest.java index 0db2d77c01..7f329b1411 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNodeTest.java @@ -97,7 +97,7 @@ class TbAssignToCustomerNodeTest extends AbstractRuleNodeUpgradeTest { private final Edge EDGE = new Edge(); private final Dashboard DASHBOARD = new Dashboard(); - private final TenantId TENANT_ID = new TenantId(UUID.fromString("c818385f-e661-407f-8c52-daf2dddf406d")); + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("c818385f-e661-407f-8c52-daf2dddf406d")); private final RuleNodeId RULE_NODE_ID = new RuleNodeId(UUID.fromString("c3570bd0-c0bc-4609-97a4-6f57d7c8b809")); private static Stream givenUnsupportedOriginatorType_whenOnMsg_thenVerifyExceptionThrown() { diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java index 60924002da..50c54b91de 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java @@ -111,7 +111,7 @@ public class TbCreateRelationNodeTest extends AbstractRuleNodeUpgradeTest { return supportedEntityTypes.stream().filter(entityType -> !entityType.equals(EntityType.TENANT)).map(Arguments::of); } - private static final TenantId tenantId = new TenantId(UUID.fromString("6fc86fc9-b25c-4893-b340-51cf4e101ab2")); + private static final TenantId tenantId = TenantId.fromUUID(UUID.fromString("6fc86fc9-b25c-4893-b340-51cf4e101ab2")); private static final DeviceId deviceId = new DeviceId(UUID.fromString("191ab124-1d8d-4749-97c6-fc84c113c1f5")); private static final AssetId assetId = new AssetId(UUID.fromString("a47a5867-deab-4333-b845-88cb1695990c")); private static final CustomerId customerId = new CustomerId(UUID.fromString("4af69229-273d-40de-9fba-f49f87373d23")); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeTest.java index a8087cc40b..f6ef490aba 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeTest.java @@ -108,7 +108,7 @@ public class TbDeleteRelationNodeTest extends AbstractRuleNodeUpgradeTest { return supportedEntityTypes.stream().filter(entityType -> !entityType.equals(EntityType.TENANT)).map(Arguments::of); } - private static final TenantId tenantId = new TenantId(UUID.fromString("6fdb457d-0910-401c-8880-abc251e6a1e2")); + private static final TenantId tenantId = TenantId.fromUUID(UUID.fromString("6fdb457d-0910-401c-8880-abc251e6a1e2")); private static final DeviceId deviceId = new DeviceId(UUID.fromString("4eef91a7-8865-4c3c-837d-ed6f6577508b")); private static final AssetId assetId = new AssetId(UUID.fromString("f4fd3b10-3f36-4d46-a162-5e62050774cc")); private static final CustomerId customerId = new CustomerId(UUID.fromString("ab890af2-3622-41e0-ac94-14d50af84348")); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNodeTest.java index de891c13d4..dd1307b10a 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNodeTest.java @@ -98,7 +98,7 @@ class TbUnassignFromCustomerNodeTest extends AbstractRuleNodeUpgradeTest { private final Edge EDGE = new Edge(); private final Dashboard DASHBOARD = new Dashboard(); - private final TenantId TENANT_ID = new TenantId(UUID.fromString("06fcc15f-2677-436d-a1cb-7754bd0bcccf")); + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("06fcc15f-2677-436d-a1cb-7754bd0bcccf")); private final ListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java index 557fb5b71d..b0788a1817 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java @@ -58,7 +58,7 @@ class TbAssetTypeSwitchNodeTest { @BeforeEach void setUp() throws TbNodeException { - TenantId tenantId = new TenantId(UUID.randomUUID()); + TenantId tenantId = TenantId.fromUUID(UUID.randomUUID()); assetId = new AssetId(UUID.randomUUID()); assetIdDeleted = new AssetId(UUID.randomUUID()); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java index d8a302ae92..9155221a26 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java @@ -50,7 +50,7 @@ import static org.mockito.Mockito.when; class TbCheckAlarmStatusNodeTest { - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final DeviceId DEVICE_ID = new DeviceId(UUID.randomUUID()); private static final AlarmId ALARM_ID = new AlarmId(UUID.randomUUID()); private static final DirectListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java index e6011c74d8..fb8ad655c0 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java @@ -63,7 +63,7 @@ import static org.mockito.Mockito.when; class TbCheckRelationNodeTest extends AbstractRuleNodeUpgradeTest { - private final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private final DeviceId ORIGINATOR_ID = new DeviceId(UUID.randomUUID()); private final DirectListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; private final TbMsg EMPTY_POST_ATTRIBUTES_MSG = TbMsg.newMsg() diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java index 55e9c33b7e..ebbdbe14c7 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java @@ -58,7 +58,7 @@ class TbDeviceTypeSwitchNodeTest { @BeforeEach void setUp() throws TbNodeException { - TenantId tenantId = new TenantId(UUID.randomUUID()); + TenantId tenantId = TenantId.fromUUID(UUID.randomUUID()); deviceId = new DeviceId(UUID.randomUUID()); deviceIdDeleted = new DeviceId(UUID.randomUUID()); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNodeTest.java index 3ae26e6560..963e25f6b6 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNodeTest.java @@ -64,7 +64,7 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class TbRuleChainInputNodeTest extends AbstractRuleNodeUpgradeTest { - private final TenantId TENANT_ID = new TenantId(UUID.fromString("4ba69ea5-6b27-42df-ab66-e7a727a67027")); + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("4ba69ea5-6b27-42df-ab66-e7a727a67027")); private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("97731954-2147-4176-8f1a-d14f1b73e4e6")); private final AssetId ASSET_ID = new AssetId(UUID.fromString("841a47bd-4e8e-4ea5-88e6-420da0d70e51")); // A stable "current" rule chain ID: this node lives here. Must differ from any target used in tests. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java index 5e9726ec97..3940ab56c4 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java @@ -76,7 +76,7 @@ import static org.mockito.Mockito.when; public class TbGetCustomerDetailsNodeTest { private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID()); - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final ListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; @Mock private TbContext ctxMock; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java index 4f267c0dfb..f9a230a437 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java @@ -60,7 +60,7 @@ import static org.mockito.BDDMockito.then; @ExtendWith(MockitoExtension.class) public class TbGetDeviceAttrNodeTest extends AbstractRuleNodeUpgradeTest { - private final TenantId TENANT_ID = new TenantId(UUID.fromString("5aea576c-66c4-4732-86b8-dc6bfcde7443")); + private final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("5aea576c-66c4-4732-86b8-dc6bfcde7443")); private final DeviceId DEVICE_ID = new DeviceId(UUID.fromString("40b6b393-6ddf-47f9-973a-18550ca70384")); private final ListeningExecutor executor = DirectListeningExecutor.INSTANCE; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java index fff7437fdf..a0d0a5a957 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java @@ -59,7 +59,7 @@ import static org.mockito.Mockito.when; public class TbGetOriginatorFieldsNodeTest { private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID()); - private static final TenantId DUMMY_TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId DUMMY_TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final ListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; @Mock private TbContext ctxMock; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java index a31d23db55..88195973e6 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java @@ -91,7 +91,7 @@ import static org.mockito.Mockito.when; public class TbGetRelatedAttributeNodeTest { private static final EntityId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID()); - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final ListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; @Mock private TbContext ctxMock; @@ -427,7 +427,7 @@ public class TbGetRelatedAttributeNodeTest { @Test public void givenFetchTelemetryToMetaData_whenOnMsg_thenShouldFetchTelemetryToMetaData() { // GIVEN - var tenant = new Tenant(new TenantId(UUID.randomUUID())); + var tenant = new Tenant(TenantId.fromUUID(UUID.randomUUID())); var device = new Device(new DeviceId(UUID.randomUUID())); prepareMsgAndConfig(TbMsgSource.METADATA, DataToFetch.LATEST_TELEMETRY, tenant.getId()); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java index 88db3dc0cd..fa528a724c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java @@ -70,7 +70,7 @@ import static org.mockito.Mockito.when; public class TbGetTenantAttributeNodeTest { private static final DeviceId DUMMY_DEVICE_ORIGINATOR = new DeviceId(UUID.randomUUID()); - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final DirectListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; @Mock private TbContext ctxMock; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java index b77bd263f8..7f476ea775 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java @@ -73,7 +73,7 @@ public class TbGetTenantDetailsNodeTest { config = new TbGetTenantDetailsNodeConfiguration().defaultConfiguration(); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); tenant = new Tenant(); - tenant.setId(new TenantId(UUID.randomUUID())); + tenant.setId(TenantId.fromUUID(UUID.randomUUID())); tenant.setTitle("Tenant title"); tenant.setCountry("Tenant country"); tenant.setCity("Tenant city"); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java index d1bcc4559e..75dc8d227a 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java @@ -104,7 +104,7 @@ public class EntitiesFieldsAsyncLoaderTest { @BeforeAll public static void setup() { RANDOM_UUID = UUID.randomUUID(); - TENANT_ID = new TenantId(UUID.randomUUID()); + TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); SUPPORTED_ENTITY_TYPES = EnumSet.of( EntityType.TENANT, EntityType.CUSTOMER, @@ -172,7 +172,7 @@ public class EntitiesFieldsAsyncLoaderTest { private void initMocks(EntityType entityType, boolean entityDoesNotExist) { switch (entityType) { case TENANT: - var tenant = Futures.immediateFuture(entityDoesNotExist ? null : new Tenant(new TenantId(RANDOM_UUID))); + var tenant = Futures.immediateFuture(entityDoesNotExist ? null : new Tenant(TenantId.fromUUID(RANDOM_UUID))); when(ctxMock.getDbCallbackExecutor()).thenReturn(DB_EXECUTOR); when(ctxMock.getTenantService()).thenReturn(tenantServiceMock); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java index 23e98dfc58..6a840a1ae3 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java @@ -48,7 +48,7 @@ import static org.mockito.Mockito.when; public class EntitiesRelatedDeviceIdAsyncLoaderTest { private static final EntityId DUMMY_ORIGINATOR = new DeviceId(UUID.randomUUID()); - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final ListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; @Mock private TbContext ctxMock; diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java index 1131586a07..edeb72ba59 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java @@ -55,7 +55,7 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; public class EntitiesRelatedEntityIdAsyncLoaderTest { private static final EntityId ASSET_ORIGINATOR_ID = new AssetId(UUID.randomUUID()); - private static final TenantId TENANT_ID = new TenantId(UUID.randomUUID()); + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final ListeningExecutor DB_EXECUTOR = DirectListeningExecutor.INSTANCE; private TbContext ctxMock; From 8314e1403c1b0b09d844d8243484324f63d9ac1f Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Sat, 25 Apr 2026 00:09:18 +0200 Subject: [PATCH 15/59] Migrated 17 deprecated Validator.validateId(UUIDBased, String) calls to the Function-based signature on lts-4.2 Wrapped each literal error message in an id-ignoring lambda so the IncorrectParameterException message stays byte-identical. --- .../server/controller/BaseController.java | 4 +-- .../BaseComponentDescriptorService.java | 2 +- .../server/dao/rule/BaseRuleChainService.java | 28 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index de69c239e9..13135aa72f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -657,7 +657,7 @@ public abstract class BaseController { protected & HasTenantId, I extends EntityId> E checkEntityId(I entityId, ThrowingBiFunction findingFunction, Operation operation) throws ThingsboardException { try { - validateId((UUIDBased) entityId, "Invalid entity id"); + validateId((UUIDBased) entityId, id -> "Invalid entity id"); SecurityUser user = getCurrentUser(); E entity = findingFunction.apply(user.getTenantId(), entityId); checkNotNull(entity, entityId.getEntityType().getNormalName() + " with id [" + entityId + "] is not found"); @@ -939,7 +939,7 @@ public abstract class BaseController { } private CalculatedField checkCalculatedFieldId(CalculatedFieldId calculatedFieldId, Operation operation) throws ThingsboardException { - validateId(calculatedFieldId, "Invalid entity id"); + validateId(calculatedFieldId, id -> "Invalid entity id"); SecurityUser user = getCurrentUser(); CalculatedField cf = calculatedFieldService.findById(user.getTenantId(), calculatedFieldId); checkNotNull(cf, calculatedFieldId.getEntityType().getNormalName() + " with id [" + calculatedFieldId + "] is not found"); diff --git a/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java b/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java index ccf145be21..ac9e43270f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java @@ -60,7 +60,7 @@ public class BaseComponentDescriptorService implements ComponentDescriptorServic @Override public ComponentDescriptor findById(TenantId tenantId, ComponentDescriptorId componentId) { - Validator.validateId(componentId, "Incorrect component id for search request."); + Validator.validateId(componentId, id -> "Incorrect component id for search request."); return componentDescriptorDao.findById(tenantId, componentId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index c96ba0542f..4061c75097 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -182,7 +182,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Transactional @Override public RuleChainUpdateResult saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData, Function ruleNodeUpdater, boolean publishSaveEvent) { - Validator.validateId(ruleChainMetaData.getRuleChainId(), "Incorrect rule chain id."); + Validator.validateId(ruleChainMetaData.getRuleChainId(), id -> "Incorrect rule chain id."); RuleChain ruleChain = findRuleChainById(tenantId, ruleChainMetaData.getRuleChainId()); if (ruleChain == null) { return RuleChainUpdateResult.failed(); @@ -335,7 +335,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId) { - Validator.validateId(ruleChainId, "Incorrect rule chain id."); + Validator.validateId(ruleChainId, id -> "Incorrect rule chain id."); RuleChain ruleChain = findRuleChainById(tenantId, ruleChainId); if (ruleChain == null) { return null; @@ -376,37 +376,37 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public RuleChain findRuleChainById(TenantId tenantId, RuleChainId ruleChainId) { - Validator.validateId(ruleChainId, "Incorrect rule chain id for search request."); + Validator.validateId(ruleChainId, id -> "Incorrect rule chain id for search request."); return ruleChainDao.findById(tenantId, ruleChainId.getId()); } @Override public RuleNode findRuleNodeById(TenantId tenantId, RuleNodeId ruleNodeId) { - Validator.validateId(ruleNodeId, "Incorrect rule node id for search request."); + Validator.validateId(ruleNodeId, id -> "Incorrect rule node id for search request."); return ruleNodeDao.findById(tenantId, ruleNodeId.getId()); } @Override public ListenableFuture findRuleChainByIdAsync(TenantId tenantId, RuleChainId ruleChainId) { - Validator.validateId(ruleChainId, "Incorrect rule chain id for search request."); + Validator.validateId(ruleChainId, id -> "Incorrect rule chain id for search request."); return ruleChainDao.findByIdAsync(tenantId, ruleChainId.getId()); } @Override public ListenableFuture findRuleNodeByIdAsync(TenantId tenantId, RuleNodeId ruleNodeId) { - Validator.validateId(ruleNodeId, "Incorrect rule node id for search request."); + Validator.validateId(ruleNodeId, id -> "Incorrect rule node id for search request."); return ruleNodeDao.findByIdAsync(tenantId, ruleNodeId.getId()); } @Override public RuleChain getRootTenantRuleChain(TenantId tenantId) { - Validator.validateId(tenantId, "Incorrect tenant id for search request."); + Validator.validateId(tenantId, id -> "Incorrect tenant id for search request."); return ruleChainDao.findRootRuleChainByTenantIdAndType(tenantId.getId(), RuleChainType.CORE); } @Override public List getRuleChainNodes(TenantId tenantId, RuleChainId ruleChainId) { - Validator.validateId(ruleChainId, "Incorrect rule chain id for search request."); + Validator.validateId(ruleChainId, id -> "Incorrect rule chain id for search request."); List relations = getRuleChainToNodeRelations(tenantId, ruleChainId); List ruleNodes = new ArrayList<>(); for (EntityRelation relation : relations) { @@ -422,7 +422,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public List getReferencingRuleChainNodes(TenantId tenantId, RuleChainId ruleChainId) { - Validator.validateId(ruleChainId, "Incorrect rule chain id for search request."); + Validator.validateId(ruleChainId, id -> "Incorrect rule chain id for search request."); List relations = getNodeToRuleChainRelations(tenantId, ruleChainId); List ruleNodes = new ArrayList<>(); for (EntityRelation relation : relations) { @@ -436,7 +436,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public List getRuleNodeRelations(TenantId tenantId, RuleNodeId ruleNodeId) { - Validator.validateId(ruleNodeId, "Incorrect rule node id for search request."); + Validator.validateId(ruleNodeId, id -> "Incorrect rule node id for search request."); List relations = relationService.findByFrom(tenantId, ruleNodeId, RelationTypeGroup.RULE_NODE); List validRelations = new ArrayList<>(); for (EntityRelation relation : relations) { @@ -463,7 +463,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public PageData findTenantRuleChainsByType(TenantId tenantId, RuleChainType type, PageLink pageLink) { - Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request."); + Validator.validateId(tenantId, id -> "Incorrect tenant id for search rule chain request."); Validator.validatePageLink(pageLink); return ruleChainDao.findRuleChainsByTenantIdAndType(tenantId.getId(), type, pageLink); } @@ -476,7 +476,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override @Transactional public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) { - Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request."); + Validator.validateId(ruleChainId, id -> "Incorrect rule chain id for delete request."); RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId()); if (ruleChain == null) { return; @@ -515,7 +515,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Transactional @Override public void deleteRuleChainsByTenantId(TenantId tenantId) { - Validator.validateId(tenantId, "Incorrect tenant id for delete rule chains request."); + Validator.validateId(tenantId, id -> "Incorrect tenant id for delete rule chains request."); tenantRuleChainsRemover.removeEntities(tenantId, tenantId); } @@ -527,7 +527,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public RuleChainData exportTenantRuleChains(TenantId tenantId, PageLink pageLink) { - Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request."); + Validator.validateId(tenantId, id -> "Incorrect tenant id for search rule chain request."); Validator.validatePageLink(pageLink); PageData ruleChainData = ruleChainDao.findRuleChainsByTenantId(tenantId.getId(), pageLink); List ruleChains = ruleChainData.getData(); From 8e8dcd493339e29ac393006f5d05d5333e51decd Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Mon, 27 Apr 2026 08:55:19 +0200 Subject: [PATCH 16/59] Replace deprecated PathChildrenCache with CuratorCache in ZK discovery Switches the ZooKeeper-based service discovery from the deprecated org.apache.curator.framework.recipes.cache.PathChildrenCache to the modern CuratorCache replacement (Curator 5.x). - ZkDiscoveryService: field type, construction, listener registration and child-event handler migrated to the new API. parentPathFilter and zkNodesDir guard preserve the original direct-children semantics against the recursive-by-default behaviour of CuratorCache. - ZkDiscoveryServiceTest: mock type and event construction adapted to the new listener signature; existing assertions unchanged. Eliminates 11 [WARNING] lines for PathChildrenCache deprecation on lts-4.2 (targeted Tier 3 slice of #15481): repo-wide [WARNING] count 843 -> 832, [ERROR] count 0 -> 0. --- .../queue/discovery/ZkDiscoveryService.java | 47 ++++++++++--------- .../discovery/ZkDiscoveryServiceTest.java | 31 ++++++------ 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java index ccc242a1a3..a1cbe6332e 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java @@ -26,9 +26,8 @@ import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.imps.CuratorFrameworkState; import org.apache.curator.framework.recipes.cache.ChildData; -import org.apache.curator.framework.recipes.cache.PathChildrenCache; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; +import org.apache.curator.framework.recipes.cache.CuratorCache; +import org.apache.curator.framework.recipes.cache.CuratorCacheListener; import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionStateListener; import org.apache.curator.retry.RetryForever; @@ -54,12 +53,12 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent.Type.CHILD_REMOVED; +import static org.apache.curator.framework.recipes.cache.CuratorCacheAccessor.parentPathFilter; @Service @ConditionalOnProperty(prefix = "zk", value = "enabled", havingValue = "true", matchIfMissing = false) @Slf4j -public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheListener { +public class ZkDiscoveryService implements DiscoveryService { @Value("${zk.url}") private String zkUrl; @@ -84,7 +83,7 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi private ScheduledExecutorService zkExecutorService; @Getter private CuratorFramework client; - private PathChildrenCache cache; + private CuratorCache cache; private String nodePath; private String zkNodesDir; @@ -117,7 +116,8 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi @Override public List getOtherServers() { - return cache.getCurrentData().stream() + return cache.stream() + .filter(parentPathFilter(zkNodesDir)) .filter(cd -> !cd.getPath().equals(nodePath)) .map(cd -> { try { @@ -241,7 +241,7 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi client = CuratorFrameworkFactory.newClient(zkUrl, zkSessionTimeout, zkConnectionTimeout, new RetryForever(zkRetryInterval)); client.start(); client.blockUntilConnected(); - cache = new PathChildrenCache(client, zkNodesDir, true); + cache = CuratorCache.builder(client, zkNodesDir).build(); cache.start(); stopped = false; log.info("ZK client connected"); @@ -254,7 +254,7 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi } private void subscribeToEvents() { - cache.getListenable().addListener(this); + cache.listenable().addListener(this::onCacheEvent); } private void unpublishCurrentServer() { @@ -286,29 +286,32 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi return "The " + propertyName + " property need to be set!"; } - @Override - public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception { + @SneakyThrows + void onCacheEvent(CuratorCacheListener.Type type, ChildData oldData, ChildData newData) { if (stopped) { - log.debug("Ignoring {}. Service is stopped.", pathChildrenCacheEvent); + log.debug("Ignoring {}. Service is stopped.", type); return; } if (client.getState() != CuratorFrameworkState.STARTED) { - log.debug("Ignoring {}, ZK client is not started, ZK client state [{}]", pathChildrenCacheEvent, client.getState()); + log.debug("Ignoring {}, ZK client is not started, ZK client state [{}]", type, client.getState()); return; } - ChildData data = pathChildrenCacheEvent.getData(); + ChildData data = type == CuratorCacheListener.Type.NODE_DELETED ? oldData : newData; if (data == null) { - log.debug("Ignoring {} due to empty child data", pathChildrenCacheEvent); + log.debug("Ignoring {} due to empty child data", type); return; } else if (data.getData() == null) { - log.debug("Ignoring {} due to empty child's data", pathChildrenCacheEvent); + log.debug("Ignoring {} due to empty child's data", type); + return; + } else if (zkNodesDir.equals(data.getPath())) { + log.debug("Ignoring event about parent node {}", data.getPath()); return; } else if (nodePath != null && nodePath.equals(data.getPath())) { - if (pathChildrenCacheEvent.getType() == CHILD_REMOVED) { + if (type == CuratorCacheListener.Type.NODE_DELETED) { log.info("ZK node for current instance is somehow deleted."); publishCurrentServer(); } - log.debug("Ignoring event about current server {}", pathChildrenCacheEvent); + log.debug("Ignoring event about current server {}", data.getPath()); return; } TransportProtos.ServiceInfo instance; @@ -322,9 +325,9 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi String serviceId = instance.getServiceId(); ProtocolStringList serviceTypesList = instance.getServiceTypesList(); - log.trace("Processing [{}] event for [{}]", pathChildrenCacheEvent.getType(), serviceId); - switch (pathChildrenCacheEvent.getType()) { - case CHILD_ADDED: + log.trace("Processing [{}] event for [{}]", type, serviceId); + switch (type) { + case NODE_CREATED: ScheduledFuture task = delayedTasks.remove(serviceId); if (task != null) { if (task.cancel(false)) { @@ -341,7 +344,7 @@ public class ZkDiscoveryService implements DiscoveryService, PathChildrenCacheLi recalculatePartitions(); } break; - case CHILD_REMOVED: + case NODE_DELETED: zkExecutorService.submit(() -> applicationEventPublisher.publishEvent(new OtherServiceShutdownEvent(this, serviceId, serviceTypesList))); ScheduledFuture future = zkExecutorService.schedule(() -> { log.debug("[{}] Going to recalculate partitions due to removed node [{}]", diff --git a/common/queue/src/test/java/org/thingsboard/server/queue/discovery/ZkDiscoveryServiceTest.java b/common/queue/src/test/java/org/thingsboard/server/queue/discovery/ZkDiscoveryServiceTest.java index 74bf30dca6..a7be216f66 100644 --- a/common/queue/src/test/java/org/thingsboard/server/queue/discovery/ZkDiscoveryServiceTest.java +++ b/common/queue/src/test/java/org/thingsboard/server/queue/discovery/ZkDiscoveryServiceTest.java @@ -18,8 +18,8 @@ package org.thingsboard.server.queue.discovery; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.imps.CuratorFrameworkState; import org.apache.curator.framework.recipes.cache.ChildData; -import org.apache.curator.framework.recipes.cache.PathChildrenCache; -import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; +import org.apache.curator.framework.recipes.cache.CuratorCache; +import org.apache.curator.framework.recipes.cache.CuratorCacheListener; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -36,8 +36,8 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.ScheduledExecutorService; -import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent.Type.CHILD_ADDED; -import static org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent.Type.CHILD_REMOVED; +import static org.apache.curator.framework.recipes.cache.CuratorCacheListener.Type.NODE_CREATED; +import static org.apache.curator.framework.recipes.cache.CuratorCacheListener.Type.NODE_DELETED; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -63,12 +63,10 @@ public class ZkDiscoveryServiceTest { private CuratorFramework client; @Mock - private PathChildrenCache cache; - - @Mock - private CuratorFramework curatorFramework; + private CuratorCache cache; private ZkDiscoveryService zkDiscoveryService; + private List dataList; private static final long RECALCULATE_DELAY = 100L; @@ -89,12 +87,13 @@ public class ZkDiscoveryServiceTest { ReflectionTestUtils.setField(zkDiscoveryService, "zkExecutorService", zkExecutorService); ReflectionTestUtils.setField(zkDiscoveryService, "recalculateDelay", RECALCULATE_DELAY); ReflectionTestUtils.setField(zkDiscoveryService, "zkDir", "/thingsboard"); + ReflectionTestUtils.setField(zkDiscoveryService, "zkNodesDir", "/thingsboard/nodes"); when(serviceInfoProvider.getServiceInfo()).thenReturn(currentInfo); - List dataList = new ArrayList<>(); + dataList = new ArrayList<>(); dataList.add(currentData); - when(cache.getCurrentData()).thenReturn(dataList); + when(cache.stream()).thenAnswer(inv -> dataList.stream()); } @Test @@ -178,14 +177,14 @@ public class ZkDiscoveryServiceTest { verify(partitionService, times(1)).recalculatePartitions(eq(currentInfo), eq(List.of(anotherInfo, childInfo))); } - private void startNode(ChildData data) throws Exception { - cache.getCurrentData().add(data); - zkDiscoveryService.childEvent(curatorFramework, new PathChildrenCacheEvent(CHILD_ADDED, data)); + private void startNode(ChildData data) { + dataList.add(data); + zkDiscoveryService.onCacheEvent(NODE_CREATED, null, data); } - private void stopNode(ChildData data) throws Exception { - cache.getCurrentData().remove(data); - zkDiscoveryService.childEvent(curatorFramework, new PathChildrenCacheEvent(CHILD_REMOVED, data)); + private void stopNode(ChildData data) { + dataList.remove(data); + zkDiscoveryService.onCacheEvent(NODE_DELETED, data, null); } } From eaa00ab83b9c137067f0a4fdc477b93a55a27318 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Mon, 27 Apr 2026 09:45:21 +0200 Subject: [PATCH 17/59] Replace deprecated RestTemplateBuilder setConnectTimeout/setReadTimeout with non-deprecated variants Spring Boot 3.5 deprecated RestTemplateBuilder.setConnectTimeout(Duration) and setReadTimeout(Duration) for removal; their non-deprecated replacements connectTimeout(Duration) and readTimeout(Duration) are direct, behavior-equivalent delegations. --- .../channels/MicrosoftTeamsNotificationChannel.java | 4 ++-- .../main/java/org/thingsboard/monitoring/client/TbClient.java | 4 ++-- .../notification/channels/impl/SlackNotificationChannel.java | 4 ++-- .../service/transport/impl/HttpTransportHealthChecker.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MicrosoftTeamsNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MicrosoftTeamsNotificationChannel.java index d023ed9b53..459c857d02 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/MicrosoftTeamsNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MicrosoftTeamsNotificationChannel.java @@ -54,8 +54,8 @@ public class MicrosoftTeamsNotificationChannel implements NotificationChannel Date: Mon, 27 Apr 2026 11:37:35 +0200 Subject: [PATCH 18/59] Create ZK nodes container before starting CuratorCache PathChildrenCache invoked EnsureContainers internally during start(), so the parent znode existed when publishCurrentServer ran. CuratorCache does not, so on a fresh ZK creatingParentsIfNeeded reaches ZKPaths.mkdirs with the trailing-slash forPath argument and fails with "Path must not end with / character", aborting Spring startup. --- .../thingsboard/server/queue/discovery/ZkDiscoveryService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java index a1cbe6332e..47c2761020 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java @@ -241,6 +241,7 @@ public class ZkDiscoveryService implements DiscoveryService { client = CuratorFrameworkFactory.newClient(zkUrl, zkSessionTimeout, zkConnectionTimeout, new RetryForever(zkRetryInterval)); client.start(); client.blockUntilConnected(); + client.createContainers(zkNodesDir); cache = CuratorCache.builder(client, zkNodesDir).build(); cache.start(); stopped = false; From c33546be5e45240466d3508b2f3b314e32f70181 Mon Sep 17 00:00:00 2001 From: Oleksandra Matviienko Date: Mon, 27 Apr 2026 15:08:24 +0200 Subject: [PATCH 19/59] Replace deprecated JsonNode.fields, HttpMessageNotReadableException(String), Assert.assertThat(Matcher), io.jsonwebtoken.SignatureException, StopWatch.getLastTaskTimeNanos calls with non-deprecated variants --- .../service/security/model/token/JwtTokenFactory.java | 2 +- .../security/model/token/OAuth2AppTokenFactory.java | 2 +- .../transport/lwm2m/AbstractLwM2MIntegrationTest.java | 2 +- .../server/transport/http/DeviceApiControllerTest.java | 7 ++++--- .../java/org/thingsboard/common/util/JacksonUtil.java | 7 ++----- .../java/org/thingsboard/common/util/TbStopWatch.java | 6 +++--- .../rule/engine/ai/Langchain4jJsonSchemaAdapter.java | 2 +- .../rule/engine/transform/TbCopyKeysNode.java | 5 +---- .../thingsboard/client/tools/i18n/TranslationPruner.java | 9 ++------- 9 files changed, 16 insertions(+), 26 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java b/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java index 5b4f4dc94a..2eced691a5 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/token/JwtTokenFactory.java @@ -23,9 +23,9 @@ import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.JwtParser; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.SignatureException; import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SignatureException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java b/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java index 98f9215ebf..a353aac86b 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/token/OAuth2AppTokenFactory.java @@ -20,9 +20,9 @@ import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.SignatureException; import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SignatureException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 8d0f0f2af0..90f9679343 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -101,10 +101,10 @@ import java.util.concurrent.atomic.AtomicLong; import static org.awaitility.Awaitility.await; import static org.eclipse.leshan.client.object.Security.noSec; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.timeout; diff --git a/common/transport/http/src/test/java/org/thingsboard/server/transport/http/DeviceApiControllerTest.java b/common/transport/http/src/test/java/org/thingsboard/server/transport/http/DeviceApiControllerTest.java index 397ea791c6..fcdb2b04ea 100644 --- a/common/transport/http/src/test/java/org/thingsboard/server/transport/http/DeviceApiControllerTest.java +++ b/common/transport/http/src/test/java/org/thingsboard/server/transport/http/DeviceApiControllerTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.http; import com.google.gson.JsonParseException; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.http.HttpInputMessage; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.context.request.async.DeferredResult; @@ -37,7 +38,7 @@ class DeviceApiControllerTest { }; var callback = new DeviceApiController.DeviceAuthCallback(transportContext, responseWriter, onSuccess); - callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax")); + callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax", (HttpInputMessage) null)); callback.onError(new JsonParseException("Json ; expected")); @@ -51,7 +52,7 @@ class DeviceApiControllerTest { DeferredResult responseWriter = Mockito.mock(DeferredResult.class); var callback = new DeviceApiController.DeviceProvisionCallback(responseWriter); - callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax")); + callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax", (HttpInputMessage) null)); callback.onError(new JsonParseException("Json ; expected")); @@ -71,7 +72,7 @@ class DeviceApiControllerTest { var callback = new DeviceApiController.GetOtaPackageCallback(transportContext, responseWriter, title, version, chunkSize, chunk); - callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax")); + callback.onError(new HttpMessageNotReadableException("JSON incorrect syntax", (HttpInputMessage) null)); callback.onError(new JsonParseException("Json ; expected")); diff --git a/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java b/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java index 9913210c1a..d6785934a2 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java +++ b/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java @@ -434,10 +434,8 @@ public class JacksonUtil { private static void toFlatMap(JsonNode node, String currentPath, Map map) { if (node.isObject()) { - Iterator> fields = node.fields(); currentPath = currentPath.isEmpty() ? "" : currentPath + "."; - while (fields.hasNext()) { - Map.Entry entry = fields.next(); + for (Map.Entry entry : node.properties()) { toFlatMap(entry.getValue(), currentPath + entry.getKey(), map); } } else if (node.isValueNode()) { @@ -541,8 +539,7 @@ public class JacksonUtil { } } else if (node.isObject()) { ObjectNode on = (ObjectNode) node; - for (Iterator> it = on.fields(); it.hasNext(); ) { - var kv = it.next(); + for (Map.Entry kv : on.properties()) { if (variableName != null) { tasks.add(task.next(kv.getValue(), variableName, kv.getKey())); } else { diff --git a/common/util/src/main/java/org/thingsboard/common/util/TbStopWatch.java b/common/util/src/main/java/org/thingsboard/common/util/TbStopWatch.java index 3a8b94c56e..fab0a72d3d 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/TbStopWatch.java +++ b/common/util/src/main/java/org/thingsboard/common/util/TbStopWatch.java @@ -52,17 +52,17 @@ public class TbStopWatch extends StopWatch { public long stopAndGetTotalTimeNanos(){ stop(); - return getLastTaskTimeNanos(); + return lastTaskInfo().getTimeNanos(); } public long stopAndGetLastTaskTimeMillis(){ stop(); - return getLastTaskTimeMillis(); + return lastTaskInfo().getTimeMillis(); } public long stopAndGetLastTaskTimeNanos(){ stop(); - return getLastTaskTimeNanos(); + return lastTaskInfo().getTimeNanos(); } } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/Langchain4jJsonSchemaAdapter.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/Langchain4jJsonSchemaAdapter.java index afe4372101..a6d1c60730 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/Langchain4jJsonSchemaAdapter.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/Langchain4jJsonSchemaAdapter.java @@ -94,7 +94,7 @@ final class Langchain4jJsonSchemaAdapter { JsonNode propertiesNode = objectSchema.get("properties"); if (propertiesNode != null) { - propertiesNode.fields().forEachRemaining(entry -> { + propertiesNode.properties().forEach(entry -> { String key = entry.getKey(); JsonNode value = entry.getValue(); builder.addProperty(key, parse(value)); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java index 08919f37fe..f9e732a53d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java @@ -29,7 +29,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -87,9 +86,7 @@ public class TbCopyKeysNode extends TbAbstractTransformNodeWithTbMsgSource { msgData = JacksonUtil.toString(msgDataNode); break; case DATA: - Iterator> iteratorNode = dataNode.fields(); - while (iteratorNode.hasNext()) { - Map.Entry entry = iteratorNode.next(); + for (Map.Entry entry : dataNode.properties()) { String msgKey = entry.getKey(); JsonNode msgValue = entry.getValue(); if (matches(msgKey)) { diff --git a/tools/src/main/java/org/thingsboard/client/tools/i18n/TranslationPruner.java b/tools/src/main/java/org/thingsboard/client/tools/i18n/TranslationPruner.java index 4181180521..6467c72114 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/i18n/TranslationPruner.java +++ b/tools/src/main/java/org/thingsboard/client/tools/i18n/TranslationPruner.java @@ -25,7 +25,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.File; import java.io.IOException; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -37,9 +36,7 @@ public class TranslationPruner { */ private static void collectKeys(JsonNode node, String prefix, Set keys) { if (!node.isObject()) return; - Iterator> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry entry = fields.next(); + for (Map.Entry entry : node.properties()) { String key = entry.getKey(); String fullKey = prefix.isEmpty() ? key : prefix + "." + key; keys.add(fullKey); @@ -52,9 +49,7 @@ public class TranslationPruner { */ private static ObjectNode pruneNode(ObjectNode node, Set keys, String prefix, ObjectMapper mapper) { ObjectNode pruned = mapper.createObjectNode(); - Iterator> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry entry = fields.next(); + for (Map.Entry entry : node.properties()) { String key = entry.getKey(); JsonNode value = entry.getValue(); String fullKey = prefix.isEmpty() ? key : prefix + "." + key; From 5858dd0b390b0f3e5f59e2c20f1035ae416f3a8d Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 6 Mar 2026 15:47:21 +0200 Subject: [PATCH 20/59] added env section description # Conflicts: # application/src/main/resources/thingsboard.yml # msa/js-executor/config/default.yml --- .../src/main/resources/thingsboard.yml | 42 +++++++++++- msa/js-executor/config/default.yml | 64 +++++++++++-------- .../src/main/resources/tb-vc-executor.yml | 9 +++ .../src/main/resources/tb-coap-transport.yml | 16 ++++- .../src/main/resources/tb-http-transport.yml | 11 ++++ .../src/main/resources/tb-lwm2m-transport.yml | 11 ++++ .../src/main/resources/tb-mqtt-transport.yml | 12 ++++ .../src/main/resources/tb-snmp-transport.yml | 12 ++++ 8 files changed, 147 insertions(+), 30 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 2c24caa1f2..812b296790 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -15,6 +15,7 @@ # # Server common parameters +# Configures HTTP/HTTPS bind address, port, SSL, WebSocket, and REST API settings. server: # Server bind-address address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -114,11 +115,13 @@ server: reset_password_per_user: "${RESET_PASSWORD_PER_USER_RATE_LIMIT_CONFIGURATION:5:3600}" # Application info parameters +# Exposes application metadata such as version string injected at build time. app: # Application version version: "@project.version@" # Zookeeper connection parameters +# Controls ZooKeeper-based service discovery and cluster coordination for microservice deployments. zk: # Enable/disable zookeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" @@ -138,6 +141,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cluster parameters +# Controls inter-node communication statistics within a ThingsBoard cluster. cluster: stats: # Enable/Disable the cluster statistics. Calculates the number of messages sent between cluster nodes based on each type @@ -146,11 +150,13 @@ cluster: print_interval_ms: "${TB_CLUSTER_STATS_PRINT_INTERVAL_MS:10000}" # Plugins configuration parameters +# Defines classpath scan packages used to discover and register ThingsBoard extension plugins. plugins: # Comma-separated package list used during classpath scanning for plugins scan_packages: "${PLUGINS_SCAN_PACKAGES:org.thingsboard.server.extensions,org.thingsboard.rule.engine}" # Security parameters +# Configures JWT tokens, user login, device claiming, OAuth2, and CA certificate trust store. security: # JWT Token parameters jwt: # Since 3.4.2 values are persisted in the database during installation or upgrade. On Install, the key will be generated randomly if no custom value set. You can change it later from Web UI under SYS_ADMIN @@ -237,6 +243,7 @@ security: report-only: "${SECURITY_HEADERS_CONTENT_SECURITY_POLICY_REPORT_ONLY:false}" # Mail settings parameters +# Configures mail service OAuth2 token refresh and per-tenant sending rate limits. mail: oauth2: # Interval for checking refresh token expiration in seconds(by default, 1 day). @@ -245,6 +252,7 @@ mail: per_tenant_rate_limits: "${MAIL_PER_TENANT_RATE_LIMITS:}" # Usage statistics parameters +# Controls collection and reporting intervals for API usage stats at system, tenant, and customer levels. usage: stats: report: @@ -266,6 +274,7 @@ usage: report_interval: "${DEVICES_STATS_REPORT_INTERVAL:60}" # UI settings parameters +# Configures dashboard data limits and base URL for UI help assets. ui: # Dashboard parameters dashboard: @@ -277,6 +286,7 @@ ui: base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-4.2.2}" # Database telemetry parameters +# Selects the storage backend (SQL, Cassandra, or TimescaleDB) for time-series and latest telemetry data. database: ts_max_intervals: "${DATABASE_TS_MAX_INTERVALS:700}" # Max number of DB queries generated by a single API call to fetch telemetry records ts: @@ -285,6 +295,7 @@ database: type: "${DATABASE_TS_LATEST_TYPE:sql}" # cassandra, sql, or timescale (for hybrid mode, DATABASE_TS_TYPE value should be cassandra, or timescale) # Cassandra driver configuration parameters +# Configures cluster name, keyspace, SSL, credentials, socket, and query settings for the Cassandra driver. cassandra: # Thingsboard cluster name cluster_name: "${CASSANDRA_CLUSTER_NAME:Thingsboard Cluster}" @@ -403,6 +414,7 @@ cassandra: print_tenant_names: "${CASSANDRA_QUERY_TENANT_RATE_LIMITS_PRINT_TENANT_NAMES:false}" # SQL configuration parameters +# Tunes batch sizes, delays, thread counts, TTL, and partitioning for SQL-backed persistence of telemetry, events, and audit logs. sql: # Specify batch size for persisting attribute updates attributes: @@ -504,6 +516,7 @@ sql: query_timeout: "${SQL_RELATIONS_QUERY_TIMEOUT_SEC:20}" # This value has to be reasonably small to prevent the relation query from blocking all other DB calls # Actor system parameters +# Configures thread pools, timeouts, and behavior for the internal actor system processing devices, rules, and RPCs. actors: system: throughput: "${ACTORS_SYSTEM_THROUGHPUT:5}" # Number of messages the actor system will process per actor before switching to processing of messages for the next actor @@ -620,6 +633,8 @@ actors: # Time in seconds to receive calculation result. calculation_timeout: "${ACTORS_CALCULATION_TIMEOUT_SEC:5}" +# Debug settings parameters +# Configures the global default duration for debug mode used by rule chains and calculated fields. debug: settings: # Default duration (in minutes) for debug mode. Min value is 1 minute. Tenant profile settings override this one. @@ -627,6 +642,7 @@ debug: default_duration: "${DEBUG_SETTINGS_DEFAULT_DURATION_MINUTES:15}" # Cache settings parameters +# Configures cache type (Caffeine or Redis), pool size, and per-entity TTL and max-size limits for all caches. cache: # caffeine or redis(7.2 - latest compatible version) type: "${CACHE_TYPE:caffeine}" @@ -780,6 +796,7 @@ cache: spring.data.redis.repositories.enabled: false # Disable this because it is not required. # Redis/Valkey configuration parameters +# Configures standalone, cluster, or sentinel Redis connection, SSL, and connection pool settings used for caching. redis: # standalone or cluster or sentinel connection: @@ -863,6 +880,7 @@ redis: # Update version parameters +# Controls whether the platform periodically checks for new ThingsBoard releases. updates: # Enable/disable checks for the new version enabled: "${UPDATES_ENABLED:true}" @@ -891,6 +909,7 @@ spring.mvc.cors: allow-credentials: "${TB_CORS_ALLOW_CREDENTIALS:true}" # General spring parameters +# Miscellaneous Spring Boot settings for circular references, Freemarker, MVC, multipart, and JPA dialect. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. spring.freemarker.checkTemplateLocation: "false" # spring freemarker configuration spring.mvc.async.request-timeout: "${SPRING_MVC_ASYNC_REQUEST_TIMEOUT:30000}" # The default timeout for asynchronous requests in milliseconds @@ -909,6 +928,7 @@ spring.jpa.properties.hibernate.order_by.default_null_ordering: "${SPRING_JPA_PR spring.jpa.properties.hibernate.dialect: "${SPRING_JPA_DIALECT:org.thingsboard.server.dao.ThingsboardPostgreSQLDialect}" # we use custom dialect that contains ilike(arg1, arg2) function (is interpreted to postgres ILIKE operator) # SQL DAO Configuration parameters +# Configures Spring JPA, Hibernate DDL, and HikariCP datasource connections for the primary and events databases. spring: data: jpa: @@ -959,6 +979,7 @@ spring: registerMbeans: "${SPRING_EVENTS_DATASOURCE_HIKARI_REGISTER_MBEANS:false}" # Audit log parameters +# Configures audit logging levels per entity type and optional forwarding to an external sink such as Elasticsearch. audit-log: # Enable/disable audit log functionality. enabled: "${AUDIT_LOG_ENABLED:true}" @@ -1001,6 +1022,7 @@ audit-log: password: "${AUDIT_LOG_SINK_PASSWORD:}" # Password used to access external sink system # Device state parameters +# Configures device inactivity detection, state persistence strategy, and rate limits for state rule nodes. state: # Device inactivity timeout is a global configuration parameter that defines when the device will be marked as "inactive" by the server. # The parameter value is in seconds. A user can overwrite this parameter for an individual device by setting the “inactivityTimeout” server-side attribute (NOTE: expects value in milliseconds). @@ -1031,7 +1053,8 @@ state: # Refill is set to be greedy. Please refer to Bucket4j library documentation for more details. rateLimit: "${DEVICE_STATE_NODE_RATE_LIMIT_CONFIGURATION:1:1,30:60,60:3600}" -# Tbel parameters +# TBEL parameters +# Configures the ThingsBoard Expression Language (TBEL) engine: limits, timeouts, thread pool, and blacklisting. tbel: # Enable/Disable TBEL feature. enabled: "${TBEL_ENABLED:true}" @@ -1060,6 +1083,7 @@ tbel: print_interval_ms: "${TB_TBEL_STATS_PRINT_INTERVAL_MS:10000}" # JS parameters +# Configures the JavaScript execution engine (local Nashorn or remote Node.js): limits, sandboxing, and thread pools. js: # local (Nashorn Engine, deprecated) OR remote JS-Executors (NodeJS) evaluator: "${JS_EVALUATOR:local}" @@ -1107,6 +1131,7 @@ js: print_interval_ms: "${TB_JS_REMOTE_STATS_PRINT_INTERVAL_MS:10000}" # Transport configuration parameters +# Configures session management, rate limits, and protocol-specific settings for HTTP, MQTT, CoAP, LwM2M, and SNMP transports. transport: sessions: # Session inactivity timeout is a global configuration parameter that defines how long the device transport session will be opened after the last message arrives from the device. @@ -1426,6 +1451,7 @@ transport: check_interval_seconds: "${TB_TRANSPORT_SSL_CERTIFICATE_RELOAD_CHECK_INTERVAL_SECONDS:60}" # CoAP server parameters +# Configures the standalone CoAP server bind address, port, DTLS encryption, and credential settings. coap: server: # Enable/disable coap server. @@ -1510,6 +1536,7 @@ coap: dtls_session_report_timeout: "${TB_COAP_X509_DTLS_SESSION_REPORT_TIMEOUT:1800000}" # Device connectivity parameters +# Specifies the hosts, ports, and credentials exposed to the UI for generating device connection check commands. device: connectivity: http: @@ -1563,6 +1590,7 @@ device: image_version: "${DEVICE_CONNECTIVITY_GATEWAY_IMAGE_VERSION:3.8-stable}" # Edges parameters +# Controls Edge instance gRPC communication, event storage, state persistence, and statistics reporting. edges: # Enable/disable Edge instance enabled: "${EDGES_ENABLED:true}" @@ -1626,6 +1654,7 @@ edges: report-interval-millis: "${EDGES_STATS_REPORT_INTERVAL_MS:600000}" # Spring doc common parameters +# Enables or disables the OpenAPI/Swagger documentation endpoint and sets the default media type. springdoc: # If false swagger API docs will be unavailable api-docs.enabled: "${SWAGGER_ENABLED:true}" @@ -1633,6 +1662,7 @@ springdoc: default-produces-media-type: "${SWAGGER_DEFAULT_PRODUCES_MEDIA_TYPE:application/json}" # Swagger common parameters +# Configures Swagger UI metadata: title, description, contact, license, version, and API path patterns. swagger: # General swagger match pattern of swagger UI links api_path: "${SWAGGER_API_PATH:/api/**}" @@ -1662,6 +1692,7 @@ swagger: group_name: "${SWAGGER_GROUP_NAME:thingsboard}" # Queue configuration parameters +# Configures the message queue backend (in-memory or Kafka) and all topic/partition/consumer settings for each service. queue: type: "${TB_QUEUE_TYPE:in-memory}" # in-memory or kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). @@ -2072,12 +2103,14 @@ queue: processing_interval: "${TB_QUEUE_TASKS_STATS_PROCESSING_INTERVAL_MS:1000}" # Event configuration parameters +# Controls limits on debug event content size stored for rule chain and rule node execution. event: debug: # Maximum number of symbols per debug event. The event content will be truncated if needed max-symbols: "${TB_MAX_DEBUG_EVENT_SYMBOLS:4096}" # General service parameters +# Sets the deployment type (monolith or microservice) and assigns tenant profiles to specific Rule Engine instances. service: type: "${TB_SERVICE_TYPE:monolith}" # monolith or tb-core or tb-rule-engine # Unique id for this service (autogenerated if empty) @@ -2091,6 +2124,7 @@ service: executor_thread_pool_size: "${TB_RULE_ENGINE_PUBSUB_EXECUTOR_THREAD_POOL_SIZE:0}" # Metrics parameters +# Enables actuator metrics endpoint and configures system info (CPU, memory) persistence frequency and TTL. metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" @@ -2104,6 +2138,7 @@ metrics: ttl: "${METRICS_SYSTEM_INFO_TTL_DAYS:7}" # Version control parameters +# Configures thread pools and Git repository folder for entity version control (export/import) operations. vc: # Pool size for handling export tasks thread_pool_size: "${TB_VC_POOL_SIZE:6}" @@ -2114,6 +2149,7 @@ vc: repositories-folder: "${TB_VC_GIT_REPOSITORIES_FOLDER:${java.io.tmpdir}/repositories}" # Notification system parameters +# Configures thread pool size and deduplication intervals for the notification rule processing engine. notification_system: # Specify thread pool size for Notification System processing notification rules and notification sending. Recommend value <= 10 thread_pool_size: "${TB_NOTIFICATION_SYSTEM_THREAD_POOL_SIZE:10}" @@ -2122,6 +2158,7 @@ notification_system: deduplication_durations: "${TB_NOTIFICATION_RULES_DEDUPLICATION_DURATIONS:NEW_PLATFORM_VERSION:0;RATE_LIMITS:14400000;}" # General management parameters +# Configures Spring Boot Actuator endpoint exposure and health indicator settings. management: endpoints: web: @@ -2134,6 +2171,7 @@ management: enabled: "false" # Mobile application settings for Thingsboard mobile application +# Specifies domain name and store links used for the ThingsBoard Live mobile application QR code and deep links. mobileApp: # Server domain name for Thingsboard Live mobile application domain: "${TB_MOBILE_APP_DOMAIN:demo.thingsboard.io}" @@ -2142,6 +2180,8 @@ mobileApp: # Link to App Store for Thingsboard Live mobile application appStoreLink: "${TB_MOBILE_APP_APP_STORE_LINK:https://apps.apple.com/us/app/thingsboard-live/id1594355695}" +# MQTT client settings +# Configures MQTT client retransmission behavior including max attempts, initial delay, and jitter factor. mqtt: # MQTT client configuration parameters client: diff --git a/msa/js-executor/config/default.yml b/msa/js-executor/config/default.yml index 9a33190069..bde09551ac 100644 --- a/msa/js-executor/config/default.yml +++ b/msa/js-executor/config/default.yml @@ -14,41 +14,51 @@ # limitations under the License. # -queue_type: "kafka" -request_topic: "js_eval.requests" -queue_prefix: "" -http_port: "8888" # /livenessProbe +# Queue configuration +# Defines the messaging queue backend used to dispatch JS evaluation requests to the executor and receive results. +queue_type: "kafka" # Queue type used for JS evaluation requests: kafka or in-memory +request_topic: "js_eval.requests" # Kafka topic name for incoming JS evaluation requests +queue_prefix: "" # Optional prefix applied to all queue/topic names; useful for environment isolation +http_port: "8888" # HTTP port exposing the /livenessProbe health check endpoint +# JavaScript execution configuration +# Controls response polling behavior and output size limits for individual JS script executions. js: - response_poll_interval: "25" - max_result_size: "300000" + response_poll_interval: "25" # Interval in milliseconds to poll for JS execution responses + max_result_size: "300000" # Maximum allowed size in bytes of a JS execution result +# Kafka configuration +# Connection, producer, and topic settings for the Kafka message broker used as the JS evaluation queue. kafka: bootstrap: # Kafka Bootstrap Servers servers: "localhost:9092" - replication_factor: "1" + replication_factor: "1" # Number of replicas for each Kafka topic partition acks: "1" # -1 = all; 0 = no acknowledgments; 1 = only waits for the leader to acknowledge - batch_size: "128" # for producer - linger_ms: "5" # for producer + batch_size: "128" # Maximum number of bytes the producer batches per partition before sending + linger_ms: "5" # Time in milliseconds the producer waits before sending a batch, allowing more messages to accumulate partitions_consumed_concurrently: "1" # (EXPERIMENTAL) increase this value if you are planning to handle more than one partition (scale up, scale down) - this will decrease the latency - requestTimeout: "30000" # The default value in kafkajs is: 30000 - connectionTimeout: "1000" # The default value in kafkajs is: 1000 - compression: "none" # gzip, lz4 or none - topic_properties: "retention.ms:604800000;segment.bytes:52428800;retention.bytes:104857600;partitions:100;min.insync.replicas:1" - use_confluent_cloud: false - client_id: "kafkajs" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh + requestTimeout: "30000" # Time in milliseconds to wait for a response to a Kafka request before timing out + connectionTimeout: "1000" # Time in milliseconds to wait when establishing a connection to a Kafka broker + compression: "none" # Message compression codec for the producer: gzip, lz4 or none + topic_properties: "retention.ms:604800000;segment.bytes:52428800;retention.bytes:104857600;partitions:100;min.insync.replicas:1" # Semicolon-separated Kafka topic configuration properties applied on topic creation + use_confluent_cloud: false # Set to true to enable Confluent Cloud-specific configuration (SSL + SASL) + client_id: "kafkajs" # Kafka client identifier; inject the pod name to easily identify the client via kafka-consumer-groups.sh ssl: - enabled: false + enabled: false # Enable SSL/TLS for Kafka broker connections confluent: sasl: - mechanism: "PLAIN" + mechanism: "PLAIN" # SASL mechanism for Confluent Cloud authentication: PLAIN, SCRAM-SHA-256, or SCRAM-SHA-512 +# Logging configuration +# Controls log verbosity, output directory, and log file naming pattern for the JS executor service. logger: - level: "info" - path: "logs" - filename: "tb-js-executor-%DATE%.log" + level: "info" # Log level: trace, debug, info, warn, or error + path: "logs" # Directory path where log files are written + filename: "tb-js-executor-%DATE%.log" # Log file name pattern; %DATE% is replaced with the current date +# JavaScript execution and monitoring configuration +# Sandboxing, script caching, and observability settings for the JS script runtime. script: # WARNING: setting this to "false" is DANGEROUS BY DESIGN. The non-sandbox # path compiles and runs user-supplied scripts in the host realm via @@ -56,10 +66,10 @@ script: # (file system, environment variables, child_process, etc.) to script # authors. Use "false" only as a performance trade-off in trusted, # non-public clusters where every script author is fully trusted. - use_sandbox: "true" - memory_usage_trace_frequency: "1000" - script_body_trace_frequency: "10000" - stat_print_frequency: "10000" - max_active_scripts: "1000" - slow_query_log_ms: "5.000000" #millis - slow_query_log_body: "false" + use_sandbox: "true" # Run scripts inside an isolated sandbox to prevent access to Node.js internals + memory_usage_trace_frequency: "1000" # Log memory usage every N script executions + script_body_trace_frequency: "10000" # Log the script body every N script executions + stat_print_frequency: "10000" # Print execution statistics every N script executions + max_active_scripts: "1000" # Maximum number of compiled scripts kept in the cache + slow_query_log_ms: "5.000000" # Execution time threshold in milliseconds above which a script is considered slow and logged + slow_query_log_body: "false" # Log the script body when execution time exceeds slow_query_log_ms threshold diff --git a/msa/vc-executor/src/main/resources/tb-vc-executor.yml b/msa/vc-executor/src/main/resources/tb-vc-executor.yml index 9ed3299606..0fe37abf22 100644 --- a/msa/vc-executor/src/main/resources/tb-vc-executor.yml +++ b/msa/vc-executor/src/main/resources/tb-vc-executor.yml @@ -15,11 +15,13 @@ # # Spring common parameters +# Controls Spring Boot startup mode, web environment type, and bean wiring behaviour. spring.main.web-environment: "${WEB_APPLICATION_ENABLE:false}" # If you enabled process metrics you should also enable 'web-environment'. spring.main.web-application-type: "${WEB_APPLICATION_TYPE:none}" # If you enabled process metrics you should set 'web-application-type' to 'servlet' value. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. # Server common parameters +# Configures the embedded HTTP server bind address and port used for actuator and metrics endpoints. server: # Server bind address (has no effect if web-environment is disabled). address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -46,6 +48,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Queue configuration parameters +# Defines the message queue type (Kafka or in-memory) and all related producer, consumer, and topic settings. queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). @@ -196,6 +199,7 @@ queue: msg-chunk-size: "${TB_QUEUE_VC_MSG_CHUNK_SIZE:250000}" # Version control parameters +# Configures the Git-based version control executor, including thread pools and local repository storage. vc: # Pool size for handling export tasks thread_pool_size: "${TB_VC_POOL_SIZE:6}" @@ -206,6 +210,7 @@ vc: repositories-folder: "${TB_VC_GIT_REPOSITORIES_FOLDER:${java.io.tmpdir}/repositories}" # Usage statistics parameters +# Controls collection and reporting of API usage statistics at system, tenant, and customer levels. usage: stats: report: @@ -219,6 +224,7 @@ usage: pack_size: "${USAGE_STATS_REPORT_PACK_SIZE:1024}" # Metrics parameters +# Enables actuator-based metrics collection and configures histogram/timer percentile exports. metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" @@ -227,6 +233,7 @@ metrics: percentiles: "${METRICS_TIMER_PERCENTILES:0.5}" # General management parameters +# Configures Spring Boot Actuator endpoint exposure, including the metrics and info endpoints. management: endpoints: web: @@ -235,12 +242,14 @@ management: include: "${METRICS_ENDPOINTS_EXPOSE:info}" # Service common properties +# Identifies this microservice instance by type and optional unique ID for cluster coordination. service: type: "${TB_SERVICE_TYPE:tb-vc-executor}" # service type # Unique id for this service (autogenerated if empty) id: "${TB_SERVICE_ID:}" # Notification system parameters +# Defines deduplication rules for notification triggers to prevent repeated alerts within a time window. notification_system: rules: # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456' diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 1554b3fc24..f84dc04907 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -15,11 +15,13 @@ # # Spring common parameters +# Controls core Spring Boot application settings such as web environment and application type. spring.main.web-environment: "${WEB_APPLICATION_ENABLE:false}" # If you enabled process metrics you should also enable 'web-environment'. spring.main.web-application-type: "${WEB_APPLICATION_TYPE:none}" # If you enabled process metrics you should set 'web-application-type' to 'servlet' value. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. # Server common parameters +# Configures the HTTP server bind address and port for the actuator/metrics web endpoint. server: # Server bind address (has no effect if web-environment is disabled). address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -27,6 +29,7 @@ server: port: "${HTTP_BIND_PORT:8083}" # Zookeeper connection parameters. Used for service discovery. +# Defines how this service registers itself and discovers other nodes via Apache ZooKeeper. zk: # Enable/disable zookeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" @@ -46,6 +49,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cache parameters +# Configures the caching backend and per-entity cache settings used by the transport service. cache: # caffeine or redis type: "${CACHE_TYPE:redis}" @@ -55,6 +59,7 @@ cache: maxSize: "${CACHE_SPECS_ENTITY_LIMITS_MAX_SIZE:100000}" # 0 means the cache is disabled # Redis/Valkey configuration parameters +# Defines connection mode, authentication, SSL, and connection pool settings for Redis or Valkey. redis: connection: # standalone or cluster or sentinel @@ -90,9 +95,9 @@ redis: password: "${REDIS_SENTINEL_PASSWORD:}" # if set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" - # db index + # Redis logical database index to select after connecting. db: "${REDIS_DB:0}" - # db password + # Password for Redis authentication (leave empty if not required). password: "${REDIS_PASSWORD:}" # Redis username for ACL authentication (Redis 6.0+). Leave empty for legacy password-only auth username: "${REDIS_USERNAME:}" @@ -181,6 +186,7 @@ transport: check_interval_seconds: "${TB_TRANSPORT_SSL_CERTIFICATE_RELOAD_CHECK_INTERVAL_SECONDS:60}" # CoAP server parameters +# Configures the CoAP and CoAP/DTLS server endpoints, including bind addresses, timeouts, and TLS credentials. coap: # CoAP bind-address bind_address: "${COAP_BIND_ADDRESS:0.0.0.0}" @@ -262,6 +268,7 @@ coap: dtls_session_report_timeout: "${TB_COAP_X509_DTLS_SESSION_REPORT_TIMEOUT:1800000}" # Queue configuration parameters +# Defines the message queue backend (Kafka) and all topic, partition, and consumer settings for inter-service communication. queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). @@ -415,12 +422,14 @@ queue: poll_interval: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS:25}" # Service common properties +# Identifies this service instance within the ThingsBoard cluster. service: type: "${TB_SERVICE_TYPE:tb-transport}" # service type # Unique id for this service (autogenerated if empty) id: "${TB_SERVICE_ID:}" # Usage statistics parameters +# Controls reporting of API usage metrics at system, tenant, and customer levels. usage: stats: report: @@ -434,11 +443,13 @@ usage: pack_size: "${USAGE_STATS_REPORT_PACK_SIZE:1024}" # Metrics parameters +# Enables Micrometer/Actuator metrics collection and configures the exposed management endpoints. metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" # General management parameters +# Configures Spring Boot Actuator endpoint exposure for health checks and metrics scraping. management: endpoints: web: @@ -447,6 +458,7 @@ management: include: "${METRICS_ENDPOINTS_EXPOSE:info}" # Notification system parameters +# Configures deduplication rules for platform notifications to prevent repeated alerts within a time window. notification_system: rules: # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456' diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index c878887a01..44adcf6e14 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -15,6 +15,7 @@ # # Server common properties +# Configures the HTTP server bind address, port, SSL/TLS settings, and HTTP/2 support. server: # Server bind address address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -54,6 +55,7 @@ server: enabled: "${HTTP2_ENABLED:true}" # Spring common parameters +# Controls Spring Boot framework-level settings such as circular references and multipart upload limits. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. spring.servlet.multipart.max-file-size: "${SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE:50MB}" # Total file size cannot exceed 50MB when configuring file uploads spring.servlet.multipart.max-request-size: "${SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE:50MB}" # Total request size for a multipart/form-data cannot exceed 50MB @@ -78,6 +80,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cache parameters +# Defines the cache backend type and per-entity cache configuration such as TTL and maximum size. cache: # caffeine or redis type: "${CACHE_TYPE:redis}" @@ -87,6 +90,7 @@ cache: maxSize: "${CACHE_SPECS_ENTITY_LIMITS_MAX_SIZE:100000}" # 0 means the cache is disabled # Redis/Valkey configuration parameters +# Configures connection mode (standalone, cluster, sentinel), credentials, SSL, and connection pool settings. redis: # standalone or cluster or sentinel connection: @@ -166,6 +170,7 @@ redis: blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}" # HTTP server parameters +# Configures HTTP transport request timeouts, payload limits, session management, JSON processing, logging, and statistics. transport: http: # HTTP request processing timeout in milliseconds @@ -212,6 +217,7 @@ transport: check_interval_seconds: "${TB_TRANSPORT_SSL_CERTIFICATE_RELOAD_CHECK_INTERVAL_SECONDS:60}" # Queue configuration parameters +# Configures the messaging queue backend (Kafka), topic definitions, partitioning, and per-service consumer settings. queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka) . @@ -364,12 +370,14 @@ queue: poll_interval: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS:25}" # General service parameters +# Defines the service type and unique identifier used for service discovery and cluster coordination. service: type: "${TB_SERVICE_TYPE:tb-transport}" # type of service # Unique id for this service (autogenerated if empty) id: "${TB_SERVICE_ID:}" # Usage statistics parameters +# Controls reporting of API usage statistics at the system, tenant, and optional customer level. usage: stats: report: @@ -383,11 +391,13 @@ usage: pack_size: "${USAGE_STATS_REPORT_PACK_SIZE:1024}" # Metrics parameters +# Enables or disables actuator metrics collection and exposure for monitoring integrations such as Prometheus. metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" # General management parameters +# Configures Spring Boot Actuator management endpoints, including which endpoints are exposed over HTTP. management: endpoints: web: @@ -396,6 +406,7 @@ management: include: "${METRICS_ENDPOINTS_EXPOSE:info}" # Notification system parameters +# Configures notification rules, including deduplication windows to prevent repeated alerts for the same trigger. notification_system: rules: # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456' diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 51b1ad0a2b..cb554fb705 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -15,11 +15,13 @@ # # Spring common parameters +# Controls Spring Boot web environment and application type settings used for optional metrics exposure. spring.main.web-environment: "${WEB_APPLICATION_ENABLE:false}" # If you enabled process metrics you should also enable 'web-environment'. spring.main.web-application-type: "${WEB_APPLICATION_TYPE:none}" # If you enabled process metrics you should set 'web-application-type' to 'servlet' value. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. # Server common parameters +# HTTP server bind address and port, effective only when the web environment is enabled. server: # Server bind address (has no effect if web-environment is disabled). address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -46,6 +48,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cache parameters +# Configures the cache backend type and per-entity cache specifications such as TTL and maximum size. cache: # caffeine or redis type: "${CACHE_TYPE:redis}" @@ -55,6 +58,7 @@ cache: maxSize: "${CACHE_SPECS_ENTITY_LIMITS_MAX_SIZE:100000}" # 0 means the cache is disabled # Redis/Valkey configuration parameters +# Connection, authentication, SSL, and connection pool settings for the Redis or Valkey cache backend. redis: connection: # standalone or cluster or sentinel @@ -133,6 +137,7 @@ redis: blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}" # LWM2M server parameters +# Session, JSON processing, RPC, logging, and LwM2M-specific transport settings including DTLS, bootstrap, and OTA. transport: sessions: # Session inactivity timeout is a global configuration parameter that defines how long the device transport session will be opened after the last message arrives from the device. @@ -312,6 +317,7 @@ transport: check_interval_seconds: "${TB_TRANSPORT_SSL_CERTIFICATE_RELOAD_CHECK_INTERVAL_SECONDS:60}" # Queue configuration properties +# Defines the message queue backend (Kafka) and per-topic settings for transport, core, rule-engine, and JS evaluation. queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). @@ -465,12 +471,14 @@ queue: poll_interval: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS:25}" # Service common parameters +# Identifies the service type and its unique instance ID within a ThingsBoard cluster. service: type: "${TB_SERVICE_TYPE:tb-transport}" # service type # Unique id for this service (autogenerated if empty) id: "${TB_SERVICE_ID:}" # Usage statistics parameters +# Controls reporting of API usage statistics at system, tenant, and optionally customer level. usage: stats: report: @@ -484,11 +492,13 @@ usage: pack_size: "${USAGE_STATS_REPORT_PACK_SIZE:1024}" # Metrics parameters +# Enables or disables Actuator-based metrics collection (e.g., Prometheus endpoint). metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" # General management parameters +# Configures Spring Boot Actuator endpoint exposure, e.g. for Prometheus metrics scraping. management: endpoints: web: @@ -497,6 +507,7 @@ management: include: "${METRICS_ENDPOINTS_EXPOSE:info}" # Notification system parameters +# Configures deduplication rules for notification triggers to prevent repeated alerts within a time window. notification_system: rules: # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456' diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index dfe35db29c..fcdc9000bd 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -15,11 +15,13 @@ # # Spring common parameters +# Controls Spring Boot application type, web environment, and bean dependency settings. spring.main.web-environment: "${WEB_APPLICATION_ENABLE:false}" # If you enabled process metrics you should also enable 'web-environment'. spring.main.web-application-type: "${WEB_APPLICATION_TYPE:none}" # If you enabled process metrics you should set 'web-application-type' to 'servlet' value. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. # Server common parameters +# Configures the embedded HTTP server bind address and port for actuator/metrics endpoints. server: # Server bind address (has no effect if web-environment is disabled). address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -27,6 +29,7 @@ server: port: "${HTTP_BIND_PORT:8083}" # Zookeeper connection parameters. Used for service discovery. +# Defines connection, session, retry settings and the node directory path for Zookeeper-based cluster coordination. zk: # Enable/disable zookeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" @@ -46,6 +49,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cache parameters +# Configures the cache backend type (Caffeine or Redis) and per-cache TTL and size limits. cache: # caffeine or redis type: "${CACHE_TYPE:redis}" @@ -55,6 +59,7 @@ cache: maxSize: "${CACHE_SPECS_ENTITY_LIMITS_MAX_SIZE:100000}" # 0 means the cache is disabled # Redis/Valkey configuration parameters +# Covers connection mode (standalone, cluster, sentinel), SSL, credentials, and connection pool tuning. redis: # standalone or cluster or sentinel connection: @@ -134,6 +139,7 @@ redis: blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}" # MQTT server parameters +# Configures the MQTT transport layer including bind address/port, SSL, Netty tuning, session management, rate limits, and message processing options. transport: mqtt: # MQTT bind-address @@ -245,6 +251,7 @@ transport: check_interval_seconds: "${TB_TRANSPORT_SSL_CERTIFICATE_RELOAD_CHECK_INTERVAL_SECONDS:60}" # Queue configuration parameters +# Defines the messaging queue backend (Kafka), topic names, partitioning, and poll/processing settings for all platform microservices. queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). @@ -398,12 +405,14 @@ queue: poll_interval: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS:25}" # Service common properties +# Identifies this service instance within the cluster by type and optional unique ID. service: type: "${TB_SERVICE_TYPE:tb-transport}" # service type # Unique id for this service (autogenerated if empty) id: "${TB_SERVICE_ID:}" # Usage statistics parameters +# Controls reporting of API usage statistics at system, tenant, and customer levels with configurable intervals. usage: stats: report: @@ -417,11 +426,13 @@ usage: pack_size: "${USAGE_STATS_REPORT_PACK_SIZE:1024}" # Metrics parameters +# Enables or disables Micrometer actuator metrics collection for monitoring this service. metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" # General management parameters +# Configures Spring Boot Actuator endpoint exposure, including which endpoints are accessible over HTTP. management: endpoints: web: @@ -430,6 +441,7 @@ management: include: "${METRICS_ENDPOINTS_EXPOSE:info}" # Notification system parameters +# Configures deduplication rules for notification triggers to prevent repeated alerts within a defined time window. notification_system: rules: # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456' diff --git a/transport/snmp/src/main/resources/tb-snmp-transport.yml b/transport/snmp/src/main/resources/tb-snmp-transport.yml index d021030a91..4df225778e 100644 --- a/transport/snmp/src/main/resources/tb-snmp-transport.yml +++ b/transport/snmp/src/main/resources/tb-snmp-transport.yml @@ -15,11 +15,13 @@ # # Spring common parameters +# Controls Spring Boot application type and web environment settings for the SNMP transport service. spring.main.web-environment: "${WEB_APPLICATION_ENABLE:false}" # If you enabled process metrics you should also enable 'web-environment'. spring.main.web-application-type: "${WEB_APPLICATION_TYPE:none}" # If you enabled process metrics you should set 'web-application-type' to 'servlet' value. spring.main.allow-circular-references: "true" # Spring Boot configuration property that controls whether circular dependencies between beans are allowed. # Server common parameters +# Configures the embedded HTTP server bind address and port (used when web environment is enabled). server: # Server bind address (has no effect if web-environment is disabled). address: "${HTTP_BIND_ADDRESS:0.0.0.0}" @@ -27,6 +29,7 @@ server: port: "${HTTP_BIND_PORT:8083}" # Zookeeper connection parameters. Used for service discovery. +# Defines ZooKeeper connectivity, timeouts, and cluster node registration settings for service coordination. zk: # Enable/disable zookeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" @@ -46,6 +49,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cache parameters +# Specifies the caching backend (Caffeine or Redis) and per-entity cache TTL and size limits. cache: # caffeine or redis type: "${CACHE_TYPE:redis}" @@ -55,6 +59,7 @@ cache: maxSize: "${CACHE_SPECS_ENTITY_LIMITS_MAX_SIZE:100000}" # 0 means the cache is disabled # Redis/Valkey configuration parameters +# Covers standalone, cluster, and sentinel Redis connection modes, SSL, authentication, and connection pool tuning. redis: connection: # standalone or cluster or sentinel @@ -133,6 +138,7 @@ redis: blockWhenExhausted: "${REDIS_POOL_CONFIG_BLOCK_WHEN_EXHAUSTED:true}" # Snmp server parameters +# Configures the SNMP transport protocol, bind port, PDU limits, session management, JSON handling, logging, and statistics. transport: snmp: # Enable/disable SNMP transport protocol @@ -184,6 +190,7 @@ transport: print-interval-ms: "${TB_TRANSPORT_STATS_PRINT_INTERVAL_MS:60000}" # Queue configuration parameters +# Defines the message queue backend (Kafka) and topic/consumer settings for transport, core, rule-engine, and JS evaluation. queue: type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) prefix: "${TB_QUEUE_PREFIX:}" # Global queue prefix. If specified, prefix is added before default topic name: 'prefix.default_topic_name'. Prefix is applied to all topics (and consumer groups for kafka). @@ -344,12 +351,14 @@ queue: poll_interval: "${TB_QUEUE_TRANSPORT_NOTIFICATIONS_POLL_INTERVAL_MS:25}" # Service common parameters +# Identifies this service instance by type and unique ID within a ThingsBoard cluster. service: type: "${TB_SERVICE_TYPE:tb-transport}" # service type # Unique id for this service (autogenerated if empty) id: "${TB_SERVICE_ID:}" # Usage statistics parameters +# Controls collection and reporting intervals for API usage statistics at system, tenant, and customer levels. usage: stats: report: @@ -363,11 +372,13 @@ usage: pack_size: "${USAGE_STATS_REPORT_PACK_SIZE:1024}" # Metrics parameters +# Enables or disables actuator-based metrics collection (e.g., Prometheus) for the SNMP transport service. metrics: # Enable/disable actuator metrics. enabled: "${METRICS_ENABLED:false}" # General management parameters +# Configures Spring Boot Actuator endpoint exposure, including which management endpoints are accessible over HTTP. management: endpoints: web: @@ -376,6 +387,7 @@ management: include: "${METRICS_ENDPOINTS_EXPOSE:info}" # Notification system parameters +# Defines deduplication rules for notification triggers to prevent duplicate alerts within configured time windows. notification_system: rules: # Semicolon-separated deduplication durations (in millis) for trigger types. Format: 'NotificationRuleTriggerType1:123;NotificationRuleTriggerType2:456' From e5c7ecc82acb96e0355d01cb5eb3ddc952bd8889 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 1 Jun 2026 17:31:27 +0300 Subject: [PATCH 21/59] added section description --- .../src/main/resources/thingsboard.yml | 92 +++++++++---------- edqs/src/main/resources/edqs.yml | 14 +-- msa/js-executor/config/default.yml | 4 +- .../src/main/resources/tb-vc-executor.yml | 15 +-- .../src/main/resources/tb-coap-transport.yml | 30 +++--- .../src/main/resources/tb-http-transport.yml | 19 ++-- .../src/main/resources/tb-lwm2m-transport.yml | 37 ++++---- .../src/main/resources/tb-mqtt-transport.yml | 20 ++-- .../src/main/resources/tb-snmp-transport.yml | 18 ++-- 9 files changed, 126 insertions(+), 123 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 812b296790..6540888ba1 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -120,20 +120,20 @@ app: # Application version version: "@project.version@" -# Zookeeper connection parameters +# ZooKeeper connection parameters # Controls ZooKeeper-based service discovery and cluster coordination for microservice deployments. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. @@ -141,7 +141,7 @@ zk: recalculate_delay: "${ZOOKEEPER_RECALCULATE_DELAY_MS:0}" # Cluster parameters -# Controls inter-node communication statistics within a ThingsBoard cluster. +# Controls cluster statistics — tracks the number of messages exchanged between cluster nodes. cluster: stats: # Enable/Disable the cluster statistics. Calculates the number of messages sent between cluster nodes based on each type @@ -610,14 +610,14 @@ actors: response_timeout_ms: "${ACTORS_RPC_RESPONSE_TIMEOUT_MS:30000}" # Close transport session if RPC delivery timed out. If enabled, RPC will be reverted to the queued state. # Note: - # - For MQTT transport: - # - QoS level 0: This feature does not apply, as no acknowledgment is expected, and therefore no timeout is triggered. - # - QoS level 1: This feature applies, as an acknowledgment is expected. - # - QoS level 2: Unsupported. - # - For CoAP transport: - # - Confirmable requests: This feature applies, as delivery confirmation is expected. - # - Non-confirmable requests: This feature does not apply, as no delivery acknowledgment is expected. - # - For HTTP and SNPM transports: RPC is considered delivered immediately, and there is no logic to await acknowledgment. + #
  • For MQTT transport: + #
    • QoS level 0: This feature does not apply, as no acknowledgment is expected, and therefore no timeout is triggered.
    • + #
    • QoS level 1: This feature applies, as an acknowledgment is expected.
    • + #
    • QoS level 2: Unsupported.
  • + #
  • For CoAP transport: + #
    • Confirmable requests: This feature applies, as delivery confirmation is expected.
    • + #
    • Non-confirmable requests: This feature does not apply, as no delivery acknowledgment is expected.
  • + #
  • For HTTP and SNPM transports: RPC is considered delivered immediately, and there is no logic to await acknowledgment.
close_session_on_rpc_delivery_timeout: "${ACTORS_RPC_CLOSE_SESSION_ON_RPC_DELIVERY_TIMEOUT:false}" statistics: # Enable/disable actor statistics @@ -825,17 +825,17 @@ redis: # if set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" sentinel: - # name of the master node + # Name of the master node master: "${REDIS_MASTER:}" - # comma-separated list of "host:port" pairs of sentinels + # Comma-separated list of "host:port" pairs of sentinels sentinels: "${REDIS_SENTINELS:}" - # password to authenticate with sentinel + # Password to authenticate with sentinel password: "${REDIS_SENTINEL_PASSWORD:}" - # if set false will be used pool config build from values of the pool config section + # If set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" - # db index + # Redis logical database index to select after connecting. db: "${REDIS_DB:0}" - # db password + # Password for Redis authentication (leave empty if not required). password: "${REDIS_PASSWORD:}" # Redis username for ACL authentication (Redis 6.0+). Leave empty for legacy password-only auth username: "${REDIS_USERNAME:}" @@ -1148,10 +1148,10 @@ transport: activity: # This property specifies the strategy for reporting activity events within each reporting period. # The accepted values are 'FIRST', 'LAST', 'FIRST_AND_LAST' and 'ALL'. - # - 'FIRST': Only the first activity event in each reporting period is reported. - # - 'LAST': Only the last activity event in the reporting period is reported. - # - 'FIRST_AND_LAST': Both the first and last activity events in the reporting period are reported. - # - 'ALL': All activity events in the reporting period are reported. + #
  • 'FIRST': Only the first activity event in each reporting period is reported.
  • + #
  • 'LAST': Only the last activity event in the reporting period is reported.
  • + #
  • 'FIRST_AND_LAST': Both the first and last activity events in the reporting period are reported.
  • + #
  • 'ALL': All activity events in the reporting period are reported.
reporting_strategy: "${TB_TRANSPORT_ACTIVITY_REPORTING_STRATEGY:LAST}" json: # Cast String data types to Numeric if possible when processing Telemetry/Attributes JSON @@ -1269,16 +1269,16 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" - # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off + # LWM2M DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off.
# Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used - connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" + #
  • 'off' to deactivate it.
  • + #
  • 'on' to activate Connection ID support (same as CID 0 or more 0).
  • + #
  • A positive value defines generated CID size in bytes.
  • + #
  • A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic).
  • + #
  • A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used
  • + #
  • A value that are > 4: MultiNodeConnectionIdGenerator is used
+ connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:8}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" @@ -1470,15 +1470,15 @@ coap: # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off + # Default: off.
# Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used - connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" + #
  • 'off' to deactivate it.
  • + #
  • 'on' to activate Connection ID support (same as CID 0 or more 0).
  • + #
  • A positive value defines generated CID size in bytes.
  • + #
  • A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic).
  • + #
  • A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used
  • + #
  • A value that are > 4: MultiNodeConnectionIdGenerator is used
+ connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:8}" # Specify the MTU (Maximum Transmission Unit). # Should be used if LAN MTU is not used, e.g. if IP tunnels are used or if the client uses a smaller value than the LAN MTU. # Default = 1024 @@ -1494,13 +1494,13 @@ coap: # In order to negotiate smaller maximum fragment lengths, # clients MAY include an extension of type "max_fragment_length" in the (extended) client hello. # The "extension_data" field of this extension SHALL contain: - # enum { + #
 enum {
     #   2^9(1) == 512,
     #   2^10(2) == 1024,
     #   2^11(3) == 2048,
     #   2^12(4) == 4096,
     #   (255)
-    # } MaxFragmentLength;
+    # } MaxFragmentLength; 
# TLS already requires clients and servers to support fragmentation of handshake messages. max_fragment_length: "${COAP_DTLS_MAX_FRAGMENT_LENGTH:1024}" # Server DTLS credentials @@ -2180,7 +2180,7 @@ mobileApp: # Link to App Store for Thingsboard Live mobile application appStoreLink: "${TB_MOBILE_APP_APP_STORE_LINK:https://apps.apple.com/us/app/thingsboard-live/id1594355695}" -# MQTT client settings +# MQTT client parameters # Configures MQTT client retransmission behavior including max attempts, initial delay, and jitter factor. mqtt: # MQTT client configuration parameters diff --git a/edqs/src/main/resources/edqs.yml b/edqs/src/main/resources/edqs.yml index 4dc404e2ca..cad0fcaccc 100644 --- a/edqs/src/main/resources/edqs.yml +++ b/edqs/src/main/resources/edqs.yml @@ -25,19 +25,19 @@ app: # Application version version: "@project.version@" -# Zookeeper connection parameters +# ZooKeeper connection parameters zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:true}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. diff --git a/msa/js-executor/config/default.yml b/msa/js-executor/config/default.yml index bde09551ac..feae8edc4a 100644 --- a/msa/js-executor/config/default.yml +++ b/msa/js-executor/config/default.yml @@ -35,7 +35,7 @@ kafka: servers: "localhost:9092" replication_factor: "1" # Number of replicas for each Kafka topic partition acks: "1" # -1 = all; 0 = no acknowledgments; 1 = only waits for the leader to acknowledge - batch_size: "128" # Maximum number of bytes the producer batches per partition before sending + batch_size: "128" # Maximum number of messages to accumulate before triggering a batch send linger_ms: "5" # Time in milliseconds the producer waits before sending a batch, allowing more messages to accumulate partitions_consumed_concurrently: "1" # (EXPERIMENTAL) increase this value if you are planning to handle more than one partition (scale up, scale down) - this will decrease the latency requestTimeout: "30000" # Time in milliseconds to wait for a response to a Kafka request before timing out @@ -66,7 +66,7 @@ script: # (file system, environment variables, child_process, etc.) to script # authors. Use "false" only as a performance trade-off in trusted, # non-public clusters where every script author is fully trusted. - use_sandbox: "true" # Run scripts inside an isolated sandbox to prevent access to Node.js internals + use_sandbox: "true" memory_usage_trace_frequency: "1000" # Log memory usage every N script executions script_body_trace_frequency: "10000" # Log the script body every N script executions stat_print_frequency: "10000" # Print execution statistics every N script executions diff --git a/msa/vc-executor/src/main/resources/tb-vc-executor.yml b/msa/vc-executor/src/main/resources/tb-vc-executor.yml index 0fe37abf22..e540182c06 100644 --- a/msa/vc-executor/src/main/resources/tb-vc-executor.yml +++ b/msa/vc-executor/src/main/resources/tb-vc-executor.yml @@ -28,19 +28,20 @@ server: # Server bind port (has no effect if web-environment is disabled). port: "${HTTP_BIND_PORT:8086}" -# Zookeeper connection parameters. Used for service discovery. +# ZooKeeper connection parameters +# Controls ZooKeeper-based service discovery and cluster coordination for microservice deployments. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:true}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index f84dc04907..dd5b77ab00 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -28,20 +28,20 @@ server: # Server bind port (has no effect if web-environment is disabled). port: "${HTTP_BIND_PORT:8083}" -# Zookeeper connection parameters. Used for service discovery. +# ZooKeeper connection parameters. Used for service discovery. # Defines how this service registers itself and discovers other nodes via Apache ZooKeeper. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. @@ -202,15 +202,15 @@ coap: # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off + # Default: off.
# Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used - connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" + #
  • 'off' to deactivate it.
  • + #
  • 'on' to activate Connection ID support (same as CID 0 or more 0).
  • + #
  • A positive value defines generated CID size in bytes.
  • + #
  • A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic).
  • + #
  • A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used
  • + #
  • A value that are > 4: MultiNodeConnectionIdGenerator is used
+ connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:8}" # Specify the MTU (Maximum Transmission Unit). # Should be used if LAN MTU is not used, e.g. if IP tunnels are used or if the client uses a smaller value than the LAN MTU. # Default = 1024 diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index 44adcf6e14..9fe5b50db8 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -60,19 +60,20 @@ spring.main.allow-circular-references: "true" # Spring Boot configuration proper spring.servlet.multipart.max-file-size: "${SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE:50MB}" # Total file size cannot exceed 50MB when configuring file uploads spring.servlet.multipart.max-request-size: "${SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE:50MB}" # Total request size for a multipart/form-data cannot exceed 50MB -# Zookeeper connection parameters. Used for service discovery. +# ZooKeeper connection parameters +# Controls ZooKeeper-based service discovery and cluster coordination for microservice deployments. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. @@ -127,9 +128,9 @@ redis: password: "${REDIS_SENTINEL_PASSWORD:}" # if set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" - # db index + # Redis logical database index to select after connecting. db: "${REDIS_DB:0}" - # db password + # Password for Redis authentication (leave empty if not required). password: "${REDIS_PASSWORD:}" # Redis username for ACL authentication (Redis 6.0+). Leave empty for legacy password-only auth username: "${REDIS_USERNAME:}" diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index cb554fb705..161e1a39fb 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -28,19 +28,20 @@ server: # Server bind port (has no effect if web-environment is disabled). port: "${HTTP_BIND_PORT:8083}" -# Zookeeper connection parameters. Used for service discovery. +# ZooKeeper connection parameters +# Controls ZooKeeper-based service discovery and cluster coordination for microservice deployments. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. @@ -94,9 +95,9 @@ redis: password: "${REDIS_SENTINEL_PASSWORD:}" # if set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" - # db index + # Redis logical database index to select after connecting. db: "${REDIS_DB:0}" - # db password + # Password for Redis authentication (leave empty if not required). password: "${REDIS_PASSWORD:}" # Redis username for ACL authentication (Redis 6.0+). Leave empty for legacy password-only auth username: "${REDIS_USERNAME:}" @@ -171,16 +172,16 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" - # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off + # LWM2M DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off.
# Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used - connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" + #
  • 'off' to deactivate it.
  • + #
  • 'on' to activate Connection ID support (same as CID 0 or more 0).
  • + #
  • A positive value defines generated CID size in bytes.
  • + #
  • A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic).
  • + #
  • A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used
  • + #
  • A value that are > 4: MultiNodeConnectionIdGenerator is used
+ connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:8}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index fcdc9000bd..35bb11d039 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -28,20 +28,20 @@ server: # Server bind port (has no effect if web-environment is disabled). port: "${HTTP_BIND_PORT:8083}" -# Zookeeper connection parameters. Used for service discovery. -# Defines connection, session, retry settings and the node directory path for Zookeeper-based cluster coordination. +# ZooKeeper connection parameters. Used for service discovery. +# Defines connection, session, retry settings and the node directory path for ZooKeeper-based cluster coordination. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. @@ -96,9 +96,9 @@ redis: password: "${REDIS_SENTINEL_PASSWORD:}" # if set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" - # db index + # Redis logical database index to select after connecting. db: "${REDIS_DB:0}" - # db password + # Password for Redis authentication (leave empty if not required). password: "${REDIS_PASSWORD:}" # Redis username for ACL authentication (Redis 6.0+). Leave empty for legacy password-only auth username: "${REDIS_USERNAME:}" diff --git a/transport/snmp/src/main/resources/tb-snmp-transport.yml b/transport/snmp/src/main/resources/tb-snmp-transport.yml index 4df225778e..3816068d35 100644 --- a/transport/snmp/src/main/resources/tb-snmp-transport.yml +++ b/transport/snmp/src/main/resources/tb-snmp-transport.yml @@ -28,20 +28,20 @@ server: # Server bind port (has no effect if web-environment is disabled). port: "${HTTP_BIND_PORT:8083}" -# Zookeeper connection parameters. Used for service discovery. +# ZooKeeper connection parameters. Used for service discovery. # Defines ZooKeeper connectivity, timeouts, and cluster node registration settings for service coordination. zk: - # Enable/disable zookeeper discovery service. + # Enable/disable ZooKeeper discovery service. enabled: "${ZOOKEEPER_ENABLED:false}" - # Zookeeper connect string + # ZooKeeper connect string url: "${ZOOKEEPER_URL:localhost:2181}" - # Zookeeper retry interval in milliseconds + # ZooKeeper retry interval in milliseconds retry_interval_ms: "${ZOOKEEPER_RETRY_INTERVAL_MS:3000}" - # Zookeeper connection timeout in milliseconds + # ZooKeeper connection timeout in milliseconds connection_timeout_ms: "${ZOOKEEPER_CONNECTION_TIMEOUT_MS:3000}" - # Zookeeper session timeout in milliseconds + # ZooKeeper session timeout in milliseconds session_timeout_ms: "${ZOOKEEPER_SESSION_TIMEOUT_MS:3000}" - # Name of the directory in zookeeper 'filesystem' + # Name of the directory in ZooKeeper 'filesystem' zk_dir: "${ZOOKEEPER_NODES_DIR:/thingsboard}" # The recalculate_delay property is recommended in a microservices architecture setup for rule-engine services. # This property provides a pause to ensure that when a rule-engine service is restarted, other nodes don't immediately attempt to recalculate their partitions. @@ -95,9 +95,9 @@ redis: password: "${REDIS_SENTINEL_PASSWORD:}" # if set false will be used pool config build from values of the pool config section useDefaultPoolConfig: "${REDIS_USE_DEFAULT_POOL_CONFIG:true}" - # db index + # Redis logical database index to select after connecting. db: "${REDIS_DB:0}" - # db password + # Password for Redis authentication (leave empty if not required). password: "${REDIS_PASSWORD:}" # Redis username for ACL authentication (Redis 6.0+). Leave empty for legacy password-only auth username: "${REDIS_USERNAME:}" From ec5be9bfef1a56a5605bffcfbadd8ca00c19d45e Mon Sep 17 00:00:00 2001 From: Valeriia Koriavikova Date: Thu, 2 Jul 2026 18:21:15 +0300 Subject: [PATCH 22/59] Merge pull request #15847 from LeoMorgan113/feature/ticks-label-fix Fix chart axis ticks font size --- .../widget/lib/chart/time-series-chart.ts | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index ca2456e109..763c8d612d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -846,15 +846,29 @@ export class TbTimeSeriesChart { } } + private maxTickLabelHalfHeight(): number { + const axes = this.yAxisList.filter(a => a.settings.show && a.settings.showTickLabels); + if (!axes.length) { + return 0; + } + + const defaultSize = defaultTimeSeriesChartYAxisSettings.tickLabelFont.size; + const maxFontSize = Math.max(...axes.map(a => a.settings.tickLabelFont?.size || defaultSize)); + return Math.ceil(maxFontSize / 2); + } + private minTopOffset(): number { - const showTickLabels = - !!this.yAxisList.find(yAxis => yAxis.settings.show && yAxis.settings.showTickLabels); - return (this.topPointLabels) ? 25 : - (showTickLabels ? 10 : 5); + if (this.topPointLabels) { + return 25; + } + const half = this.maxTickLabelHalfHeight(); + return half ? Math.max(10, half) : 5; } private minBottomOffset(): number { - return this.settings.dataZoom ? 45 : 5; + const half = this.maxTickLabelHalfHeight(); + const minOffset = half ? Math.max(5, half) : 5; + return this.settings.dataZoom ? Math.max(45, minOffset) : minOffset; } private _onParentScroll() { @@ -883,6 +897,7 @@ export class TbTimeSeriesChart { this.updateBarsAnimation(barItems, false); } this.timeSeriesChart.resize(); + this.updateAxes(); if (this.animationEnabled()) { this.updateBarsAnimation(barItems, true); } From 5493ac7da50a506693a5b5f1ac69d6eb27842b33 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Thu, 2 Jul 2026 17:54:39 +0200 Subject: [PATCH 23/59] Fixed validation for Digital Gauge widget maxValue when it is zero (#15893) * Fixed validation for Digital Gauge widget maxValue when it is zero * Fixed check --- .../digital-simple-gauge-basic-config.component.ts | 11 +++++------ .../gauge/digital-gauge-widget-settings.component.ts | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts index e0ca65cdea..6d837f476c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/gauge/digital-simple-gauge-basic-config.component.ts @@ -30,7 +30,7 @@ import { getTimewindowConfig, setTimewindowConfig } from '@home/components/widget/config/timewindow-config-panel.component'; -import { formatValue, isDefined, isUndefined } from '@core/utils'; +import { formatValue, isDefined, isDefinedAndNotNull, isNumeric, isUndefined } from '@core/utils'; import { Component } from '@angular/core'; import { convertLevelColorsSettingsToColorProcessor, @@ -189,11 +189,10 @@ export class DigitalSimpleGaugeBasicConfigComponent extends BasicWidgetConfigCom private maxValueValidation(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { - const value: string = control.value; - if (value) { - if (value < control.parent?.get('minValue').value) { - return {maxValue: true}; - } + const value: number = control.value; + const minValue = control.parent?.get('minValue').value; + if (isNumeric(value) && isDefinedAndNotNull(minValue) && value < minValue) { + return {maxValue: true}; } return null; }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts index ff22abd28a..fe7eeb7305 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/gauge/digital-gauge-widget-settings.component.ts @@ -37,7 +37,7 @@ import { digitalGaugeLayoutTranslations, DigitalGaugeType } from '@home/components/widget/lib/digital-gauge.models'; -import { formatValue, isDefined } from '@core/utils'; +import { formatValue, isDefined, isDefinedAndNotNull, isNumeric } from '@core/utils'; import { ColorSettings, ColorType, @@ -218,11 +218,10 @@ export class DigitalGaugeWidgetSettingsComponent extends WidgetSettingsComponent private maxValueValidation(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { - const value: string = control.value; - if (value) { - if (value < control.parent?.get('minValue').value) { - return {maxValue: true}; - } + const value: number = control.value; + const minValue = control.parent?.get('minValue').value; + if (isNumeric(value) && isDefinedAndNotNull(minValue) && value < minValue) { + return {maxValue: true}; } return null; }; From 655d4ed55e7aeb88a8fcb2be9903a4ec99432b06 Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Fri, 3 Jul 2026 12:16:41 +0300 Subject: [PATCH 24/59] Fix invalid `callSuper = false` usages for EqualsAndHashCode --- .../server/service/cf/ctx/state/ScriptCalculatedFieldState.java | 2 +- .../server/service/cf/ctx/state/SimpleCalculatedFieldState.java | 2 +- .../main/java/org/thingsboard/server/common/data/EventInfo.java | 2 +- .../java/org/thingsboard/server/common/data/HomeDashboard.java | 2 +- .../java/org/thingsboard/server/common/data/TenantInfo.java | 2 +- .../org/thingsboard/server/common/data/alarm/AlarmComment.java | 2 +- .../data/device/data/CoapDeviceTransportConfiguration.java | 2 +- .../data/device/data/Lwm2mDeviceTransportConfiguration.java | 2 +- .../lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java | 2 +- .../java/org/thingsboard/server/common/data/edge/EdgeInfo.java | 2 +- .../thingsboard/server/common/data/edqs/fields/AssetFields.java | 2 +- .../server/common/data/edqs/fields/AssetProfileFields.java | 2 +- .../server/common/data/edqs/fields/CustomerFields.java | 2 +- .../server/common/data/edqs/fields/DashboardFields.java | 2 +- .../server/common/data/edqs/fields/DeviceFields.java | 2 +- .../server/common/data/edqs/fields/DeviceProfileFields.java | 2 +- .../thingsboard/server/common/data/edqs/fields/EdgeFields.java | 2 +- .../server/common/data/edqs/fields/EntityViewFields.java | 2 +- .../server/common/data/edqs/fields/QueueStatsFields.java | 2 +- .../server/common/data/edqs/fields/RuleChainFields.java | 2 +- .../server/common/data/edqs/fields/TenantFields.java | 2 +- .../server/common/data/edqs/fields/TenantProfileFields.java | 2 +- .../thingsboard/server/common/data/edqs/fields/UserFields.java | 2 +- .../thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java | 2 +- .../thingsboard/server/common/data/query/AlarmCountQuery.java | 2 +- .../java/org/thingsboard/server/common/data/queue/Queue.java | 2 +- .../org/thingsboard/server/common/data/rule/RuleNodeState.java | 2 +- .../thingsboard/server/common/data/widget/WidgetTypeInfo.java | 2 +- .../server/transport/mqtt/limits/GatewaySessionLimits.java | 2 +- .../server/dao/model/sqlts/latest/TsKvLatestEntity.java | 2 +- .../rule/engine/action/TbClearAlarmNodeConfiguration.java | 2 +- .../rule/engine/action/TbCreateAlarmNodeConfiguration.java | 2 +- .../rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java | 2 +- .../rule/engine/mqtt/azure/AzureIotHubSasCredentials.java | 2 +- .../rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java index be95922dbb..4bb5e4eca2 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/ScriptCalculatedFieldState.java @@ -36,7 +36,7 @@ import java.util.List; import java.util.Map; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @Slf4j @NoArgsConstructor public class ScriptCalculatedFieldState extends BaseCalculatedFieldState { diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java index e797376c55..7c54cefdcc 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/SimpleCalculatedFieldState.java @@ -34,7 +34,7 @@ import java.util.List; import java.util.Map; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor public class SimpleCalculatedFieldState extends BaseCalculatedFieldState { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java index e0bdde1dd8..e81ea75d93 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.id.TenantId; * @author Andrew Shvayka */ @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @Schema public class EventInfo extends BaseData { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java index df2cdf2bf5..8d9ee2104b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java @@ -21,7 +21,7 @@ import lombok.EqualsAndHashCode; @Schema @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class HomeDashboard extends Dashboard { public static final String HIDE_DASHBOARD_TOOLBAR_DESCRIPTION = "Hide dashboard toolbar flag. Useful for rendering dashboards on mobile."; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java index 8f38ecd750..6f44874a9c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.id.TenantId; @Schema @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class TenantInfo extends Tenant { @Schema(description = "Tenant Profile name", example = "Default") private String tenantProfileName; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 29269e5bd8..17211ed617 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -34,7 +34,7 @@ import java.io.Serial; @Schema @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @Builder @AllArgsConstructor public class AlarmComment extends BaseData implements HasName { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java index 662887c08c..b365686064 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java @@ -26,7 +26,7 @@ import java.util.HashMap; import java.util.Map; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class CoapDeviceTransportConfiguration extends PowerSavingConfiguration implements DeviceTransportConfiguration { private static final long serialVersionUID = 6061442236008925609L; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java index 1c53412ef9..dc9e22fe80 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/Lwm2mDeviceTransportConfiguration.java @@ -26,7 +26,7 @@ import java.util.HashMap; import java.util.Map; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class Lwm2mDeviceTransportConfiguration extends PowerSavingConfiguration implements DeviceTransportConfiguration { @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java index 14ef402718..ad5703637c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java @@ -21,7 +21,7 @@ import lombok.EqualsAndHashCode; @Schema @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class LwM2MServerSecurityConfigDefault extends LwM2MServerSecurityConfig { @Schema(description = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", accessMode = Schema.AccessMode.READ_ONLY) protected String securityHost; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java index 5dbd0212b3..66ad9f1d85 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInfo.java @@ -20,7 +20,7 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.EdgeId; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class EdgeInfo extends Edge { private String customerTitle; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java index d05147b4d7..18b410a581 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetFields.java @@ -27,7 +27,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class AssetFields extends AbstractEntityFields implements ProfileAwareFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java index c519daa800..3e336023a3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/AssetProfileFields.java @@ -23,7 +23,7 @@ import lombok.experimental.SuperBuilder; import java.util.UUID; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class AssetProfileFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java index c324f0f1ab..ad5e87134e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/CustomerFields.java @@ -26,7 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class CustomerFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java index 608a64436e..786a27fce9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DashboardFields.java @@ -29,7 +29,7 @@ import java.util.UUID; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class DashboardFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java index ef8aee952b..df72525990 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceFields.java @@ -27,7 +27,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class DeviceFields extends AbstractEntityFields implements ProfileAwareFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java index 2331829054..d7f6cf13bb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/DeviceProfileFields.java @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.DeviceProfileType; import java.util.UUID; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class DeviceProfileFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java index e048eb22a8..24ac1fcd35 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EdgeFields.java @@ -26,7 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class EdgeFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java index c5027dfc8f..d21d495cf1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/EntityViewFields.java @@ -26,7 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class EntityViewFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java index 5c5a139364..3e8a1136bc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/QueueStatsFields.java @@ -23,7 +23,7 @@ import lombok.experimental.SuperBuilder; import java.util.UUID; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class QueueStatsFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java index d580f6b913..d8dd1c8a43 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/RuleChainFields.java @@ -26,7 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class RuleChainFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java index ba350fec54..3fda35d969 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantFields.java @@ -26,7 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class TenantFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java index 5d1ff0e0e2..28f257bbf2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/TenantProfileFields.java @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.id.TenantId; import java.util.UUID; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class TenantProfileFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java index 70fde8bf9c..723b618d7c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edqs/fields/UserFields.java @@ -26,7 +26,7 @@ import java.util.UUID; import static org.thingsboard.server.common.data.edqs.fields.FieldsUtil.getText; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @SuperBuilder public class UserFields extends AbstractEntityFields { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java index f46339c15a..8ca4070671 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseDeleteTsKvQuery.java @@ -19,7 +19,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class BaseDeleteTsKvQuery extends BaseTsKvQuery implements DeleteTsKvQuery { private final Boolean rewriteLatestIfDeleted; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java index 1599413c1c..77003a9452 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/AlarmCountQuery.java @@ -31,7 +31,7 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @ToString public class AlarmCountQuery extends EntityCountQuery { private long startTs; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java b/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java index d6a4f2b12f..1e48b66c92 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/queue/Queue.java @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.validation.NoXss; import java.util.Optional; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class Queue extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, QueueConfig { private TenantId tenantId; @NoXss diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java index 0624350d7e..77c2b2068c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeState.java @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeStateId; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class RuleNodeState extends BaseData { private RuleNodeId ruleNodeId; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java index 9acce93aa3..34f397f0ed 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java @@ -27,7 +27,7 @@ import java.util.Collections; import java.util.List; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class WidgetTypeInfo extends BaseWidgetType { @Serial diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java index 8356a17748..641f52bbd3 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java @@ -19,7 +19,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class GatewaySessionLimits extends SessionLimits { private SessionRateLimits gatewayRateLimits; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java index 421a22a9d2..4d8a7de22a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java @@ -36,7 +36,7 @@ import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.VERSION_COLUMN; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @Entity @Table(name = "ts_kv_latest") @IdClass(TsKvLatestCompositeKey.class) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java index ab305919fd..a98e04e591 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNodeConfiguration.java @@ -21,7 +21,7 @@ import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.server.common.data.script.ScriptLanguage; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class TbClearAlarmNodeConfiguration extends TbAbstractAlarmNodeConfiguration implements NodeConfiguration { @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java index bf305a55d1..c97ef31e73 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java @@ -26,7 +26,7 @@ import java.util.Collections; import java.util.List; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class TbCreateAlarmNodeConfiguration extends TbAbstractAlarmNodeConfiguration implements NodeConfiguration { @NoXss diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java index 6551352823..bafc4fb64e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeConfiguration.java @@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit; * Created by ashvayka on 19.01.18. */ @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class TbGpsGeofencingActionNodeConfiguration extends TbGpsGeofencingFilterNodeConfiguration { private int minInsideDuration; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java index 93d1ef7ef8..4b9550b1d9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/AzureIotHubSasCredentials.java @@ -30,7 +30,7 @@ import org.thingsboard.rule.engine.credentials.CredentialsType; import java.security.Security; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) @Slf4j @JsonIgnoreProperties(ignoreUnknown = true) public class AzureIotHubSasCredentials extends CertPemCredentials { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java index f11173f3f9..3362526e70 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNodeConfiguration.java @@ -21,7 +21,7 @@ import lombok.EqualsAndHashCode; import org.thingsboard.rule.engine.mqtt.TbMqttNodeConfiguration; @Data -@EqualsAndHashCode(callSuper = false) +@EqualsAndHashCode(callSuper = true) public class TbAzureIotHubNodeConfiguration extends TbMqttNodeConfiguration { @Override From c0dead85520dcdecc5ee0435e48b16d8fcc0265b Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Fri, 3 Jul 2026 12:42:58 +0300 Subject: [PATCH 25/59] Address review comments: rename test config class and drop inline FQN annotations --- .../device/provision/DeviceProvisionServiceTest.java | 10 ++++++---- .../service/queue/DefaultTbClusterServiceTest.java | 3 ++- .../transport/DefaultTransportApiServiceTest.java | 10 ++++++---- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java b/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java index 4f2eaa5147..4d0195c816 100644 --- a/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/device/provision/DeviceProvisionServiceTest.java @@ -21,6 +21,8 @@ import org.assertj.core.api.Assertions; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; @@ -73,12 +75,12 @@ import static org.mockito.Mockito.when; @Slf4j @RunWith(SpringRunner.class) -@ContextConfiguration(classes = DeviceProvisionServiceTest.ContextConfiguration.class) +@ContextConfiguration(classes = DeviceProvisionServiceTest.TestConfig.class) public class DeviceProvisionServiceTest { - @org.springframework.context.annotation.Configuration - static class ContextConfiguration { - @org.springframework.context.annotation.Bean + @Configuration + static class TestConfig { + @Bean public DeviceProvisionServiceImpl deviceProvisionService(TbQueueProducerProvider producerProvider, DeviceProfileService deviceProfileService, DeviceService deviceService, diff --git a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java index 79b31acf78..b4f36d9bb5 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbClusterServiceTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.service.queue; import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -115,7 +116,7 @@ public class DefaultTbClusterServiceTest { @MockitoSpyBean protected TbClusterService clusterService; - @org.junit.Before + @Before public void setUp() { lenient().when(topicService.getNotificationsTopic(any(), any())).thenAnswer(invocation -> { ServiceType serviceType = invocation.getArgument(0); diff --git a/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java b/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java index 6b667cc811..be3cc2e92b 100644 --- a/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/transport/DefaultTransportApiServiceTest.java @@ -20,6 +20,8 @@ import lombok.extern.slf4j.Slf4j; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; import org.springframework.test.context.ContextConfiguration; @@ -69,12 +71,12 @@ import static org.mockito.Mockito.when; @Slf4j @RunWith(SpringRunner.class) -@ContextConfiguration(classes = DefaultTransportApiServiceTest.ContextConfiguration.class) +@ContextConfiguration(classes = DefaultTransportApiServiceTest.TestConfig.class) public class DefaultTransportApiServiceTest { - @org.springframework.context.annotation.Configuration - static class ContextConfiguration { - @org.springframework.context.annotation.Bean + @Configuration + static class TestConfig { + @Bean public DefaultTransportApiService defaultTransportApiService(TbDeviceProfileCache deviceProfileCache, TbTenantProfileCache tenantProfileCache, TbApiUsageStateService apiUsageStateService, From e2969dd381e154faa31f3532b238d7e0dac6f2be Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Mon, 6 Jul 2026 11:59:25 +0300 Subject: [PATCH 26/59] Version set to 4.2.2.4-SNAPSHOT --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/discovery-api/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/edge-api/src/main/proto/edge.proto | 1 + common/edqs/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/proto/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- edqs/pom.xml | 2 +- monitoring/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/edqs/pom.xml | 2 +- msa/js-executor/package.json | 2 +- msa/js-executor/pom.xml | 2 +- msa/monitoring/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/package.json | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 64 files changed, 65 insertions(+), 64 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 1ae95e99ed..9a46bbdc3a 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 61ff41ce80..7d6aba753b 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index a9d43c9ec1..4db50b2380 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index 987e6e2ffe..48d931bb53 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index c1a83ee870..d6d1d1d69b 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index c9cfeae4e7..a0f9a8be78 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index 450a0826b9..a2b9dce687 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/discovery-api/pom.xml b/common/discovery-api/pom.xml index 1c3b34f6f4..38774d93f7 100644 --- a/common/discovery-api/pom.xml +++ b/common/discovery-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index ff630f416c..9141a164d8 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto index 520b4ac493..376a4d8c5b 100644 --- a/common/edge-api/src/main/proto/edge.proto +++ b/common/edge-api/src/main/proto/edge.proto @@ -49,6 +49,7 @@ enum EdgeVersion { V_4_2_2_1 = 4221; V_4_2_2_2 = 4222; V_4_2_2_3 = 4223; + V_4_2_2_4 = 4224; V_LATEST = 99999; } diff --git a/common/edqs/pom.xml b/common/edqs/pom.xml index f107721524..ae62259f79 100644 --- a/common/edqs/pom.xml +++ b/common/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index d9184ac548..d338f57946 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index f63c12d7dc..1eb2dc44b2 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard common diff --git a/common/proto/pom.xml b/common/proto/pom.xml index 5335df00b9..c2f898bb38 100644 --- a/common/proto/pom.xml +++ b/common/proto/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index 8e684718a0..e714fc749b 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index cdfe36cd3c..46a97d2ece 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index 9f179e9b1a..0f9191e3cc 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 5791fefc6a..6752190015 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 0de5ffe6ea..ae013f938c 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index a2681241c6..79c1e4c06b 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index 4d5b6bce44..801fb49117 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index 5da25b24d0..a4892f9f80 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index 9cc958cde9..a6c0686b4b 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index b069dbe413..dc12d0d7b5 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index 2565016226..b1b2ed7343 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index ca992646a9..a11c5b17d1 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index 3c60d4f077..db60495e95 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index 09c4318a20..28a7e6e332 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 4449502857..19c089dee1 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard dao diff --git a/edqs/pom.xml b/edqs/pom.xml index 2d811909ec..bdae55999d 100644 --- a/edqs/pom.xml +++ b/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard edqs diff --git a/monitoring/pom.xml b/monitoring/pom.xml index fa8b83c6f7..2026a40f70 100644 --- a/monitoring/pom.xml +++ b/monitoring/pom.xml @@ -21,7 +21,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index e433d6bfb2..a78bea8969 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/edqs/pom.xml b/msa/edqs/pom.xml index 54a1cd91c7..74a6e58ad9 100644 --- a/msa/edqs/pom.xml +++ b/msa/edqs/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index 070bf829a5..de6339b518 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "4.2.2.3", + "version": "4.2.2.4", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 7174947cbc..f6f7961d0e 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/monitoring/pom.xml b/msa/monitoring/pom.xml index 519c928b6e..64157d6197 100644 --- a/msa/monitoring/pom.xml +++ b/msa/monitoring/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa diff --git a/msa/pom.xml b/msa/pom.xml index 2552bf188c..0847add29e 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index ba83cbb211..9be443d031 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index a20505772e..ba18c5279b 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 309536b4ef..f78e2f0f13 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index f7ea4160d1..ac25949c82 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index d80b63217c..89e99f79e2 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 0bf990171b..eb69201745 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index a711411729..399d84763c 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index f0996dc1bf..330e205394 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index 9d781e0854..fc8779250a 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index 47fff0501d..4bb404284a 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 4c58d7a94f..e5acd2a6fa 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "4.2.2.3", + "version": "4.2.2.4", "description": "ThingsBoard Web UI Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index bc40e149ff..738118d4f8 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 6a2b55cd84..9cc1f94bbe 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard netty-mqtt - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 1a2faa6cb7..7d42f9f1c7 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index 9051482016..ceadf1d118 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index 2c73670dde..75bd4e06ed 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 8d9b6e5cbc..f45cd15c34 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index dcb0f975f2..c6c2429a4f 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index 137dbaa1a7..86a17be7a5 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index 4fef3b50e7..cf4374ad9e 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 8d24e0d982..d5ff0be961 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index 99b98fa7c9..1d0fe86220 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 1d61b07440..e1c9512d05 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 3889d8d334..16052972cd 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index a1f9d384f1..cc18e3a815 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 2ac8b3a6d7..09d354e3a3 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "4.2.2.3", + "version": "4.2.2.4", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index 863463e78c..099850fb80 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 4.2.2.3-SNAPSHOT + 4.2.2.4-SNAPSHOT thingsboard org.thingsboard From 1b9b30e49c9485e2923dae5d94648d435d8599d2 Mon Sep 17 00:00:00 2001 From: Viacheslav Klimov Date: Mon, 13 Jul 2026 16:04:37 +0300 Subject: [PATCH 27/59] Move LTS version range check into LtsVersion --- .../server/service/install/lts/LtsMigrationService.java | 4 +--- .../server/service/install/lts/LtsVersion.java | 8 ++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/install/lts/LtsMigrationService.java b/application/src/main/java/org/thingsboard/server/service/install/lts/LtsMigrationService.java index ccafa88234..580db32666 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/lts/LtsMigrationService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/lts/LtsMigrationService.java @@ -126,9 +126,7 @@ public class LtsMigrationService { // so a cross-family upgrade is fully handled by the target-family migrations. // Excluding the dormant older-family beans avoids double-processing. static boolean isInRangeForTargetFamily(LtsVersion version, LtsVersion from, LtsVersion to) { - return version.sameFamily(to) - && version.compareTo(from) > 0 - && version.compareTo(to) <= 0; + return version.sameFamily(to) && version.isInRange(from, to); } private void runSchemaUpdate(String version) { diff --git a/application/src/main/java/org/thingsboard/server/service/install/lts/LtsVersion.java b/application/src/main/java/org/thingsboard/server/service/install/lts/LtsVersion.java index cb55e61b3e..9a0fa5be34 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/lts/LtsVersion.java +++ b/application/src/main/java/org/thingsboard/server/service/install/lts/LtsVersion.java @@ -37,6 +37,14 @@ public record LtsVersion(int major, int minor, int maintenance, int patch) imple return major == other.major && minor == other.minor; } + /** + * Half-open range check: {@code from < this <= to}. The lower bound is exclusive (a source already at + * {@code from} has applied that version) and the upper bound inclusive (the target version's own migration runs). + */ + public boolean isInRange(LtsVersion from, LtsVersion to) { + return compareTo(from) > 0 && compareTo(to) <= 0; + } + @Override public int compareTo(LtsVersion o) { int c = Integer.compare(major, o.major); From 4448c3c646e9597f0fe7f160cc5d90d7c753a645 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Tue, 21 Jul 2026 11:20:07 +0200 Subject: [PATCH 28/59] Updated functionality block at System Administrator level --- ui-ngx/src/assets/dashboard/sys_admin_home_page.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json index 739402e72f..860afa84c8 100644 --- a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json @@ -194,7 +194,8 @@ "padding": "16px", "settings": { "useMarkdownTextFunction": false, - "markdownTextPattern": "
\n
\n
\n
widgets.functions.title
\n
\n {{ 'widgets.functions.switch-to-pe' | translate }}\n
\n
\n
\n
widgets.functions.alarms
\n
widgets.functions.dashboards
\n
widgets.functions.entities-and-relations
\n
widgets.functions.profiles
\n
widgets.functions.advanced-features
\n
\n
\n
widgets.functions.notification-center
\n
widgets.functions.api-usage
\n
widgets.functions.customers
\n
widgets.functions.customers-hierarchy
\n
widgets.functions.roles-and-permissions
\n
\n
\n
widgets.functions.groups
\n
widgets.functions.integrations
\n
widgets.functions.solution-templates
\n
widgets.functions.scheduler
\n
widgets.functions.white-labeling
\n
\n
\n
", + "markdownTextPattern": "
\n
\n
\n
widgets.functions.title
\n
\n {{ 'widgets.functions.switch-to-pe' | translate }}\n
\n
\n
\n
widgets.functions.alarms
\n
widgets.functions.dashboards
\n
widgets.functions.entities-and-relations
\n
widgets.functions.profiles
\n
widgets.functions.advanced-features
\n
widgets.functions.solution-templates
\n
\n
\n
widgets.functions.notification-center
\n
widgets.functions.api-usage
\n
widgets.functions.customers
\n
widgets.functions.customers-hierarchy
\n
widgets.functions.roles-and-permissions
\n
\n
\n
widgets.functions.groups
\n
widgets.functions.integrations
\n
widgets.functions.scheduler
\n
widgets.functions.white-labeling
\n
\n
\n
", + "markdownTextFunction": "return '# Some title\\\\n - Entity name: ' + data[0]['entityName'];", "applyDefaultMarkdownStyle": false, "markdownCss": ".tb-card-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n}\n\n.tb-card-content {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: row;\n margin-top: 4px;\n overflow: auto;\n}\n\n.tb-card-column {\n min-width: 0px;\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.feature {\n position: relative;\n cursor: default;\n font-weight: 400;\n font-size: 14px;\n line-height: 28px;\n letter-spacing: 0.2px;\n color: rgba(0, 0, 0, 0.76);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.feature:before {\n content: \"check\";\n font-family: 'Material Icons Round';\n display: inline-block;\n font-size: 20px;\n line-height: 20px;\n color: #198038;\n font-weight: 600;\n position: relative;\n background: #F3F6FA;\n border-radius: 4px;\n width: 20px;\n height: 20px;\n padding: 2px;\n vertical-align: sub;\n margin-right: 8px;\n}\n\n.feature.pe:before {\n content: \"close\";\n background: #F4F4F4;\n color: rgba(0, 0, 0, 0.12);\n}\n\n.feature.pe:after {\n position: relative;\n display: inline-block;\n margin-left: 4px;\n vertical-align: baseline;\n top: -0.5em;\n content: \"PE\";\n color: #305680;\n font-weight: 700;\n font-size: 12px;\n line-height: 12px;\n letter-spacing: 0.0015em;\n}\n\n.feature+.feature {\n margin-top: 4px;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-switch-to-pe {\n height: 24px;\n font-size: 12px;\n padding: 0 4px;\n }\n \n .feature+.feature {\n margin-top: 2px;\n }\n \n .feature {\n font-size: 11px;\n line-height: 18px;\n }\n\n .feature:before {\n font-size: 14px;\n line-height: 14px;\n width: 14px;\n height: 14px;\n margin-right: 4px;\n }\n .feature.pe:after {\n margin-left: 2px;\n top: -0.5em;\n content: \"PE\";\n font-size: 8px;\n line-height: 8px;\n }\n \n}\n\n" }, From 6d349707f61de03d60dfcbc26cc85b67424aa71a Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Thu, 30 Jul 2026 16:22:11 +0200 Subject: [PATCH 29/59] Changed sequence --- ui-ngx/src/assets/dashboard/sys_admin_home_page.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json index 860afa84c8..97ef4feb2d 100644 --- a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json @@ -194,7 +194,7 @@ "padding": "16px", "settings": { "useMarkdownTextFunction": false, - "markdownTextPattern": "
\n
\n
\n
widgets.functions.title
\n
\n {{ 'widgets.functions.switch-to-pe' | translate }}\n
\n
\n
\n
widgets.functions.alarms
\n
widgets.functions.dashboards
\n
widgets.functions.entities-and-relations
\n
widgets.functions.profiles
\n
widgets.functions.advanced-features
\n
widgets.functions.solution-templates
\n
\n
\n
widgets.functions.notification-center
\n
widgets.functions.api-usage
\n
widgets.functions.customers
\n
widgets.functions.customers-hierarchy
\n
widgets.functions.roles-and-permissions
\n
\n
\n
widgets.functions.groups
\n
widgets.functions.integrations
\n
widgets.functions.scheduler
\n
widgets.functions.white-labeling
\n
\n
\n
", + "markdownTextPattern": "
\n
\n
\n
widgets.functions.title
\n
\n {{ 'widgets.functions.switch-to-pe' | translate }}\n
\n
\n
\n
widgets.functions.alarms
\n
widgets.functions.dashboards
\n
widgets.functions.entities-and-relations
\n
widgets.functions.profiles
\n
widgets.functions.advanced-features
\n
\n
\n
widgets.functions.notification-center
\n
widgets.functions.api-usage
\n
widgets.functions.customers
\n
widgets.functions.solution-templates
\n
widgets.functions.customers-hierarchy
\n
\n
\n
widgets.functions.roles-and-permissions
\n
widgets.functions.groups
\n
widgets.functions.integrations
\n
widgets.functions.scheduler
\n
widgets.functions.white-labeling
\n
\n
\n
", "markdownTextFunction": "return '# Some title\\\\n - Entity name: ' + data[0]['entityName'];", "applyDefaultMarkdownStyle": false, "markdownCss": ".tb-card-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n}\n\n.tb-card-content {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: row;\n margin-top: 4px;\n overflow: auto;\n}\n\n.tb-card-column {\n min-width: 0px;\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.feature {\n position: relative;\n cursor: default;\n font-weight: 400;\n font-size: 14px;\n line-height: 28px;\n letter-spacing: 0.2px;\n color: rgba(0, 0, 0, 0.76);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.feature:before {\n content: \"check\";\n font-family: 'Material Icons Round';\n display: inline-block;\n font-size: 20px;\n line-height: 20px;\n color: #198038;\n font-weight: 600;\n position: relative;\n background: #F3F6FA;\n border-radius: 4px;\n width: 20px;\n height: 20px;\n padding: 2px;\n vertical-align: sub;\n margin-right: 8px;\n}\n\n.feature.pe:before {\n content: \"close\";\n background: #F4F4F4;\n color: rgba(0, 0, 0, 0.12);\n}\n\n.feature.pe:after {\n position: relative;\n display: inline-block;\n margin-left: 4px;\n vertical-align: baseline;\n top: -0.5em;\n content: \"PE\";\n color: #305680;\n font-weight: 700;\n font-size: 12px;\n line-height: 12px;\n letter-spacing: 0.0015em;\n}\n\n.feature+.feature {\n margin-top: 4px;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-switch-to-pe {\n height: 24px;\n font-size: 12px;\n padding: 0 4px;\n }\n \n .feature+.feature {\n margin-top: 2px;\n }\n \n .feature {\n font-size: 11px;\n line-height: 18px;\n }\n\n .feature:before {\n font-size: 14px;\n line-height: 14px;\n width: 14px;\n height: 14px;\n margin-right: 4px;\n }\n .feature.pe:after {\n margin-left: 2px;\n top: -0.5em;\n content: \"PE\";\n font-size: 8px;\n line-height: 8px;\n }\n \n}\n\n" From 6de4b30e5ff22848cbab5cb26eb951c5c6b685c5 Mon Sep 17 00:00:00 2001 From: Nikita Mazurenko Date: Tue, 4 Aug 2026 16:01:34 +0300 Subject: [PATCH 30/59] Unblock and interrupt edge event consumer on session destroy --- .../server/service/edge/rpc/EdgeGrpcSession.java | 2 +- .../server/service/edge/rpc/KafkaEdgeGrpcSession.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index fb420d080a..1e9a0ade87 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -760,7 +760,7 @@ public abstract class EdgeGrpcSession implements Closeable { ctx.getClusterService().onEdgeEventUpdate(new EdgeEventUpdateMsg(edge.getTenantId(), edge.getId())); } - private void stopCurrentSendDownlinkMsgsTask(Boolean isInterrupted) { + protected void stopCurrentSendDownlinkMsgsTask(Boolean isInterrupted) { if (sessionState.getSendDownlinkMsgsFuture() != null && !sessionState.getSendDownlinkMsgsFuture().isDone()) { sessionState.getSendDownlinkMsgsFuture().set(isInterrupted); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java index 67c0a19e66..e1acc08ba3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/KafkaEdgeGrpcSession.java @@ -156,6 +156,7 @@ public class KafkaEdgeGrpcSession extends EdgeGrpcSession { @Override public boolean destroy() { + stopCurrentSendDownlinkMsgsTask(true); try { if (consumer != null) { log.info("[{}][{}] Stopping edge event consumer...", tenantId, edge != null ? edge.getId() : null); @@ -180,9 +181,13 @@ public class KafkaEdgeGrpcSession extends EdgeGrpcSession { private void awaitConsumerTermination() { try { - consumerExecutor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS); + if (!consumerExecutor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) { + // without this the thread is leaked for the whole remaining delivery-retry window (or forever, if the future is never completed). + consumerExecutor.shutdownNow(); + } } catch (InterruptedException ie) { log.warn("[{}][{}] Interrupted while awaiting consumer executor termination", tenantId, edge.getId()); + Thread.currentThread().interrupt(); } } From e2617bcd8e15f34e1ed6d1240a2577e5af5f248c Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Wed, 5 Aug 2026 16:06:22 +0300 Subject: [PATCH 31/59] Fix TelemetryObserveStrategy enum values in OpenAPI spec --- .../device/profile/lwm2m/TelemetryObserveStrategy.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryObserveStrategy.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryObserveStrategy.java index 53dafe19b7..615bd4f32e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryObserveStrategy.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryObserveStrategy.java @@ -15,8 +15,13 @@ */ package org.thingsboard.server.common.data.device.profile.lwm2m; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; +@Schema(description = "Observation strategy for telemetry. " + + "SINGLE (0): one resource equals one single observe request. " + + "COMPOSITE_ALL (1): all resources in one composite observe request. " + + "COMPOSITE_BY_OBJECT (2): grouped composite observe requests by object.") public enum TelemetryObserveStrategy { SINGLE("One resource equals one single observe request", 0), @@ -52,8 +57,4 @@ public enum TelemetryObserveStrategy { throw new IllegalArgumentException("Unknown TelemetryObserveStrategy id: " + id); } - @Override - public String toString() { - return name() + " (" + id + "): " + description; - } } From b31845e4beecfbb684b068e265604e8d5f45c152 Mon Sep 17 00:00:00 2001 From: Dmytro Pinkevych <49400214+pinkevmladchy@users.noreply.github.com> Date: Thu, 13 Aug 2026 16:43:01 +0300 Subject: [PATCH 32/59] Merge pull request #16028 from pinkevmladchy/iot-hub-built-in-items Open built-in IoT Hub items locally instead of installing duplicates --- ui-ngx/src/app/core/http/widget.service.ts | 2 +- .../dashboard-widget-select.component.html | 13 +- .../dashboard-widget-select.component.ts | 41 ++++- .../iot-hub/iot-hub-actions.service.ts | 79 +++++++++- .../iot-hub-add-item-dialog.component.ts | 15 ++ .../iot-hub/iot-hub-built-in.service.ts | 146 ++++++++++++++++++ .../iot-hub-install-dialog.component.html | 2 +- .../iot-hub-install-dialog.component.ts | 11 ++ .../iot-hub/iot-hub-item-card.component.html | 32 ++-- .../iot-hub/iot-hub-item-card.component.ts | 13 +- .../iot-hub-item-detail-dialog.component.html | 28 ++-- .../iot-hub-item-detail-dialog.component.ts | 32 ++++ .../home/components/iot-hub/iot-hub-utils.ts | 52 ++++++- .../home-page/iot-hub-widget.component.html | 20 ++- .../lib/home-page/iot-hub-widget.component.ts | 7 +- .../models/iot-hub/iot-hub-version.models.ts | 8 + .../assets/locale/locale.constant-en_US.json | 7 + 17 files changed, 457 insertions(+), 51 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-built-in.service.ts diff --git a/ui-ngx/src/app/core/http/widget.service.ts b/ui-ngx/src/app/core/http/widget.service.ts index 06a6c86ddd..e4e50cc830 100644 --- a/ui-ngx/src/app/core/http/widget.service.ts +++ b/ui-ngx/src/app/core/http/widget.service.ts @@ -188,7 +188,7 @@ export class WidgetService { } public getWidgetType(fullFqn: string, config?: RequestConfig): Observable { - return this.http.get(`/api/widgetType?fqn=${fullFqn}`, + return this.http.get(`/api/widgetType?fqn=${encodeURIComponent(fullFqn)}`, defaultHttpOptionsFromConfig(config)); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html index 7d2ea9cdb5..6da41a9878 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.html @@ -370,7 +370,8 @@ - +
{{item.name}} @@ -405,10 +406,12 @@ {{ 'iot-hub.installed' | translate }} } - - file_download - {{ item.totalInstallCount | shortNumber }} - + @if (!isIotHubWidgetBuiltIn(item)) { + + file_download + {{ item.totalInstallCount | shortNumber }} + + }
diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts index 3034cee011..46d4e06e91 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-widget-select.component.ts @@ -39,7 +39,14 @@ import { ItemType, FilterParamInfo, WidgetCategory } from '@shared/models/iot-hu import { IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models'; import { IotHubApiService } from '@core/http/iot-hub-api.service'; import { IotHubActionsService } from '@home/components/iot-hub/iot-hub-actions.service'; -import { filterIotHubItemsBySearch, groupIotHubFilterItems, IotHubFilterGroup, resolveIotHubItemImageUrl } from '@home/components/iot-hub/iot-hub-utils'; +import { + filterIotHubItemsBySearch, + groupIotHubFilterItems, + IotHubFilterGroup, + isBuiltInItem, + resolveIotHubItemImageUrl +} from '@home/components/iot-hub/iot-hub-utils'; +import { IotHubBuiltInService } from '@home/components/iot-hub/iot-hub-built-in.service'; type selectWidgetMode = 'installed' | 'iotHub'; type installedSubMode = 'default' | 'allWidgets'; @@ -278,6 +285,7 @@ export class DashboardWidgetSelectComponent { constructor(private widgetsService: WidgetService, private iotHubApiService: IotHubApiService, private iotHubActions: IotHubActionsService, + private iotHubBuiltInService: IotHubBuiltInService, private translate: TranslateService, private cd: ChangeDetectorRef) { @@ -494,6 +502,13 @@ export class DashboardWidgetSelectComponent { } return; } + if (isBuiltInItem(item)) { + // Built-in widgets ship with the platform: pick the local widget type matched by fqn + // instead of installing a duplicate, exactly like an already installed item. + this.selectBuiltInWidget(item); + return; + } + // Built-in items never reach the dialog (they return above), so anything added from it installs. this.iotHubActions.openItemDetail(item, undefined, undefined, 'add').subscribe(result => { if (result?.action === 'add') { this.installAndAddWidget(result.item); @@ -505,6 +520,10 @@ export class DashboardWidgetSelectComponent { return this.installedWidgets?.some(i => i.itemId === item.itemId) ?? false; } + isIotHubWidgetBuiltIn(item: MpItemVersionView): boolean { + return isBuiltInItem(item); + } + getIotHubItemImage(item: MpItemVersionView): string | null { return resolveIotHubItemImageUrl(item, this.iotHubApiService); } @@ -737,6 +756,26 @@ export class DashboardWidgetSelectComponent { this.cd.markForCheck(); } + private selectBuiltInWidget(item: MpItemVersionView): void { + this.iotHubBuiltInService.resolveLocalWidgetTypeInfo(item).subscribe(lookup => { + if (lookup.value) { + this.widgetSelected.emit(this.toWidgetInfo(lookup.value)); + return; + } + if (lookup.failed) { + // Existence is unknown — installing now could duplicate a widget that is still there. + this.iotHubActions.showBuiltInLookupFailed(item); + return; + } + // The local copy is gone (e.g. deleted by a sysadmin) — installing is the only way back. + this.iotHubActions.confirmInstallMissingBuiltIn(item).subscribe(confirmed => { + if (confirmed) { + this.installAndAddWidget(item); + } + }); + }); + } + private installAndAddWidget(item: MpItemVersionView): void { const versionId = item.id as string; this.iotHubApiService.installItemVersion(versionId, { ignoreLoading: true }).subscribe({ diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-actions.service.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-actions.service.ts index 73e627fbe6..cd3d48d5d5 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-actions.service.ts +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-actions.service.ts @@ -17,6 +17,7 @@ import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Observable, of, EMPTY } from 'rxjs'; +import { map, switchMap } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { DialogService } from '@core/services/dialog.service'; import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models'; @@ -30,6 +31,15 @@ import { TbIotHubUpdateDialogComponent, IotHubUpdateDialogData } from './iot-hub import { TbIotHubDeleteDialogComponent, IotHubDeleteDialogData } from './iot-hub-delete-dialog.component'; import { TbDeviceInstallDialogComponent, DeviceInstallDialogData } from './device-install-dialog/device-install-dialog.component'; import { TbIotHubInstalledItemsDialogComponent, IotHubInstalledItemsDialogData } from './iot-hub-installed-items-dialog.component'; +import { IotHubBuiltInService } from './iot-hub-built-in.service'; +import { isBuiltInItem } from './iot-hub-utils'; + +/** + * What `openBuiltInOrConfirmInstall` did with a built-in item: 'handled' means nothing is left to do + * (the local copy was opened, or the user was told why it could not be), while 'install-requested' + * means the component really is absent and the user asked for it to be installed. + */ +export type IotHubBuiltInAction = 'handled' | 'install-requested'; @Injectable() export class IotHubActionsService { @@ -37,7 +47,8 @@ export class IotHubActionsService { constructor( private dialog: MatDialog, private dialogService: DialogService, - private translate: TranslateService + private translate: TranslateService, + private builtInService: IotHubBuiltInService ) {} openItemDetail(item: MpItemVersionView, installedItem?: IotHubInstalledItem, installedItemsCount?: number, @@ -72,7 +83,67 @@ export class IotHubActionsService { }).afterClosed(); } + /** + * Runs the primary action of an item: built-in content is opened locally (never installed), + * device packages are connected, everything else goes through the install dialog. + */ installItem(item: MpItemVersionView): Observable { + if (isBuiltInItem(item)) { + return this.openOrInstallBuiltIn(item); + } + return this.runInstall(item); + } + + /** Opens the local copy of a built-in item, or asks to install it when it really is absent. */ + openBuiltInOrConfirmInstall(item: MpItemVersionView): Observable { + return this.builtInService.openLocalComponent(item).pipe( + switchMap(outcome => { + switch (outcome) { + case 'missing': + return this.confirmInstallMissingBuiltIn(item).pipe( + map((confirmed): IotHubBuiltInAction => confirmed ? 'install-requested' : 'handled') + ); + case 'failed': + this.showBuiltInLookupFailed(item); + return of('handled'); + default: + // 'opened' or 'cancelled' — the component is in place either way, so never install. + return of('handled'); + } + }) + ); + } + + /** + * Asks whether to install a built-in item whose local copy is gone — the component the Hub entry + * mirrors was deleted from this instance, so installing is the only way to get it back. + */ + confirmInstallMissingBuiltIn(item: MpItemVersionView): Observable { + return this.dialogService.confirm( + this.translate.instant('iot-hub.built-in-missing-title'), + this.translate.instant('iot-hub.built-in-missing-text', { name: item?.name }), + this.translate.instant('action.cancel'), + this.translate.instant('iot-hub.install') + ); + } + + /** Reports that the local copy could not be checked — nothing was opened and nothing installed. */ + showBuiltInLookupFailed(item: MpItemVersionView): void { + this.dialogService.alert( + this.translate.instant('iot-hub.built-in-lookup-failed-title'), + this.translate.instant('iot-hub.built-in-lookup-failed-text', { name: item?.name }) + ); + } + + private openOrInstallBuiltIn(item: MpItemVersionView): Observable { + return this.openBuiltInOrConfirmInstall(item).pipe( + // The confirmation inside is the only one the user gets: install starts immediately, + // and opening the component is a separate click once it is back in the library. + switchMap(action => action === 'install-requested' ? this.runInstall(item, true) : EMPTY) + ); + } + + private runInstall(item: MpItemVersionView, skipConfirm = false): Observable { if (item.type === ItemType.ALARM_RULE) { this.dialogService.alert( this.translate.instant('iot-hub.alarm-rule-install-update-required'), @@ -81,13 +152,13 @@ export class IotHubActionsService { return EMPTY; } if (item.type === ItemType.DEVICE) { - return this.installDevice(item); + return this.openDeviceInstallDialog(item); } return this.dialog.open(TbIotHubInstallDialogComponent, { panelClass: ['tb-dialog'], disableClose: true, autoFocus: false, - data: { item } as IotHubInstallDialogData + data: { item, skipConfirm } as IotHubInstallDialogData }).afterClosed(); } @@ -121,6 +192,8 @@ export class IotHubActionsService { }).afterClosed(); } + // Reached only for items whose action mode is 'connect', i.e. never for built-in content: + // that decision is made once, at the public entry points above. installDevice(item: MpItemVersionView): Observable { return this.openDeviceInstallDialog(item); } diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.ts index e83580e271..404ec8ef03 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-add-item-dialog.component.ts @@ -27,6 +27,7 @@ import { DialogService } from '@core/services/dialog.service'; import { TranslateService } from '@ngx-translate/core'; import { EntityId } from '@shared/models/id/entity-id'; import { IotHubActionsService } from './iot-hub-actions.service'; +import { isBuiltInItem } from './iot-hub-utils'; export interface IotHubAddItemDialogData { itemType: ItemType; @@ -73,6 +74,20 @@ export class TbIotHubAddItemDialogComponent extends DialogComponent { + if (action === 'install-requested') { + this.doAddItem(item); + } + }); + return; + } + this.doAddItem(item); + } + + private doAddItem(item: MpItemVersionView): void { if (this.itemType === ItemType.DEVICE) { this.installDeviceItem(item); return; diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-built-in.service.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-built-in.service.ts new file mode 100644 index 0000000000..054bec852f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-built-in.service.ts @@ -0,0 +1,146 @@ +/// +/// Copyright © 2016-2026 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Injectable } from '@angular/core'; +import { HttpErrorResponse } from '@angular/common/http'; +import { Router } from '@angular/router'; +import { from, Observable, of } from 'rxjs'; +import { catchError, concatMap, first, map, switchMap } from 'rxjs/operators'; +import { WidgetService } from '@core/http/widget.service'; +import { MpItemVersionView } from '@shared/models/iot-hub/iot-hub-version.models'; +import { ItemType } from '@shared/models/iot-hub/iot-hub-item.models'; +import { isValidWidgetFullFqn, WidgetType, WidgetTypeInfo } from '@shared/models/widget.models'; +import { EntityType } from '@shared/models/entity-type.models'; +import { getEntityDetailsPageURL, isNotEmptyStr } from '@core/utils'; + +/** + * Result of looking up the local component a built-in Hub item mirrors. `failed` separates + * "the lookup itself did not answer" (network error, 5xx, no read permission) from "the component + * is not here": only the latter may be offered as an install, otherwise a transient error would + * hand the tenant a duplicate of a component that is still in place. + */ +export interface IotHubLocalLookup { + value: T | null; + failed: boolean; +} + +/** + * Outcome of trying to open the local component of a built-in item. 'cancelled' means the component + * is there but the router did not go — typically a route guard blocked it (unsaved changes) — so + * there is nothing to install and nothing to report. + */ +export type IotHubOpenLocalOutcome = 'opened' | 'cancelled' | 'missing' | 'failed'; + +/** + * Handles IoT Hub items marked `builtIn` — content that already ships inside ThingsBoard. + * Such an item is never installed: its `fqn` is deliberately identical to the fqn of the + * platform's own component, which is used as the match key to reach the local copy. + */ +@Injectable({ + providedIn: 'root' +}) +export class IotHubBuiltInService { + + constructor( + private router: Router, + private widgetService: WidgetService + ) {} + + /** + * Resolves the platform's own widget type mirroring a built-in Hub item, matched by fqn. + * + * There is no API to test a batch of fqns at once — `GET /api/widgetType?fqn=` is per fqn and + * carries the full descriptor, and `/api/widgetTypeFqns` is scoped to a bundle the Hub payload + * does not name — so this must stay a per-item check triggered by a click, never a prefetch + * across a catalogue page. + */ + resolveLocalWidgetType(item: MpItemVersionView): Observable> { + const noMatch: IotHubLocalLookup = { value: null, failed: false }; + const fqn = item?.dataDescriptor?.fqn; + if (!isNotEmptyStr(fqn)) { + // Without a match key nothing was asked of the server, so existence is unknown rather than + // disproven — reporting it as absent would offer an install for a component that is in place. + return of({ value: null, failed: true }); + } + // Hub items carry a bare fqn; platform widget types are addressed by a scoped full fqn. + // Built-in content is system scoped; the tenant scope covers a copy installed into this tenant, + // which matters while the installed-items list a caller filters by is still stale. + const fullFqns = isValidWidgetFullFqn(fqn) ? [fqn] : [`system.${fqn}`, `tenant.${fqn}`]; + return from(fullFqns).pipe( + concatMap(fullFqn => this.widgetService.getWidgetType(fullFqn, { ignoreErrors: true, ignoreLoading: true }).pipe( + map(widgetType => this.lookupResult(widgetType)), + catchError((err: HttpErrorResponse) => of(this.lookupFailure(err))) + )), + // Stop at the first match, and at the first hard failure too: with existence unknown, the + // remaining candidate cannot turn a failure into a trustworthy "not here". + first(lookup => !!lookup.value?.id?.id || lookup.failed, noMatch) + ); + } + + /** Same match, resolved to the info projection widget pickers need (image, description, type). */ + resolveLocalWidgetTypeInfo(item: MpItemVersionView): Observable> { + return this.resolveLocalWidgetType(item).pipe( + switchMap(lookup => lookup.value + ? this.widgetService.getWidgetTypeInfoById(lookup.value.id.id, { ignoreErrors: true, ignoreLoading: true }).pipe( + map(widgetTypeInfo => this.lookupResult(widgetTypeInfo)), + catchError((err: HttpErrorResponse) => of(this.lookupFailure(err))) + ) + : of({ value: null, failed: lookup.failed })) + ); + } + + /** Navigates to the local component a built-in item mirrors, reporting why it could not. */ + openLocalComponent(item: MpItemVersionView): Observable { + return this.resolveLocalComponentUrl(item).pipe( + switchMap(lookup => { + if (!lookup.value) { + return of(lookup.failed ? 'failed' : 'missing'); + } + // The navigation itself can still be refused — a ConfirmOnExitGuard on the page the user is + // leaving, a failing resolver — and reporting it as opened would leave them with the Hub + // dialog closed (it closes on NavigationStart) and nothing opened in its place. + return from(this.router.navigateByUrl(lookup.value)).pipe( + map((navigated): IotHubOpenLocalOutcome => navigated ? 'opened' : 'cancelled'), + catchError(() => of('cancelled')) + ); + }) + ); + } + + private resolveLocalComponentUrl(item: MpItemVersionView): Observable> { + // Only widgets (including SCADA symbol widgets) ship inside the platform today. Other item + // types have no local counterpart to match by fqn, so they count as missing. + if (item?.type !== ItemType.WIDGET) { + return of({ value: null, failed: false }); + } + return this.resolveLocalWidgetType(item).pipe( + map(lookup => ({ + value: lookup.value ? getEntityDetailsPageURL(lookup.value.id.id, EntityType.WIDGET_TYPE) || null : null, + failed: lookup.failed + })) + ); + } + + private lookupResult(value: T | null): IotHubLocalLookup { + return { value: value ?? null, failed: false }; + } + + // A 404 is an answer — the component is not here. Anything else (network error, 5xx, 403) leaves + // existence unknown, and must never be presented to the user as deleted content. + private lookupFailure(err: HttpErrorResponse): IotHubLocalLookup { + return { value: null, failed: err?.status !== 404 }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.html index ea3774ac11..25c5ca2089 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.html @@ -117,7 +117,7 @@ } @case ('installing') { -

{{ 'iot-hub.install-confirm-title' | translate:{ name: item.name } }}

+

{{ 'iot-hub.installing-title' | translate:{ name: item.name } }}

{{ 'iot-hub.install-desc' | translate }}

} @case ('success') { diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts index 43ed8d21b4..e4816d19ad 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-install-dialog.component.ts @@ -60,6 +60,13 @@ interface PendingOverwrite { export interface IotHubInstallDialogData { item: MpItemVersionView; + /** + * Starts installing right away instead of opening on the confirm step. Set by callers that + * already asked the user — e.g. a built-in item whose local copy was deleted — so the user is + * not asked to confirm the same install twice. Ignored when the item needs input first + * (entity selection, rule chain options). + */ + skipConfirm?: boolean; } export type InstallState = @@ -140,6 +147,10 @@ export class TbIotHubInstallDialogComponent extends DialogComponent{{ item.creatorDisplayName }} - · + @if (showInstallCount) { + · + } + } + @if (showInstallCount) { + download + {{ item.totalInstallCount | shortNumber }} } - download - {{ item.totalInstallCount | shortNumber }}
@if (mode === 'add') { @if (isInstalled()) { check{{ 'iot-hub.installed' | translate }} } @else { - + } } @else if (isInstalled()) { @if (isSameVersion()) { @@ -74,7 +78,7 @@ } } @else { - + } } @else { @@ -105,18 +109,22 @@ [class.clickable]="mode !== 'add'" (click)="mode !== 'add' && onCreatorClick($event)" (keyup.enter)="mode !== 'add' && onCreatorClick($event)">{{ item.creatorDisplayName }} - · + @if (showInstallCount) { + · + } + } + @if (showInstallCount) { + + download + {{ item.totalInstallCount | shortNumber }} + } - - download - {{ item.totalInstallCount | shortNumber }} - @if (mode === 'add') { @if (isInstalled()) { check{{ 'iot-hub.installed' | translate }} } @else { - + } } @else if (isInstalled()) { @if (isSameVersion()) { @@ -143,7 +151,7 @@ } } @else { - + } diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts index 2d9c13d8d7..b2fe9a58f3 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-card.component.ts @@ -20,6 +20,7 @@ import { getItemTypeIcon, ItemType } from '@shared/models/iot-hub/iot-hub-item.m import { IotHubInstalledItem } from '@shared/models/iot-hub/iot-hub-installed-item.models'; import { TranslateService } from '@ngx-translate/core'; import { IotHubApiService } from '@core/http/iot-hub-api.service'; +import { iotHubItemActionLabel, isBuiltInItem } from '@home/components/iot-hub/iot-hub-utils'; @Component({ selector: 'tb-iot-hub-item-card', @@ -29,8 +30,6 @@ import { IotHubApiService } from '@core/http/iot-hub-api.service'; }) export class TbIotHubItemCardComponent { - readonly ItemType = ItemType; - @Input() item: MpItemVersionView; @Input() installedItem: IotHubInstalledItem; @Input() installedItemsCount = 0; @@ -51,6 +50,16 @@ export class TbIotHubItemCardComponent { private iotHubApiService: IotHubApiService ) {} + // Install counters mean nothing for content the tenant already has, so the counter and the + // separator that would dangle next to it are both derived from this one boolean. + get showInstallCount(): boolean { + return !isBuiltInItem(this.item); + } + + get actionLabel(): string { + return iotHubItemActionLabel(this.item, this.mode === 'add' ? 'add' : 'card'); + } + isCompactLayout(): boolean { return this.item.type === ItemType.CALCULATED_FIELD || this.item.type === ItemType.ALARM_RULE diff --git a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html index 30d9322dd9..eba34fb30a 100644 --- a/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/iot-hub/iot-hub-item-detail-dialog.component.html @@ -30,15 +30,17 @@ {{ getTypeIcon() }} {{ typeTranslations.get(item.type) | translate }} - - - download - {{ item.totalInstallCount | shortNumber }} {{ 'iot-hub.installs' | translate }} - + @if (showInstallCount) { + + + download + {{ item.totalInstallCount | shortNumber }} {{ 'iot-hub.installs' | translate }} + + } update - v {{ item.version }} + {{ versionLabel }} @if (preview) { @@ -318,19 +320,13 @@ @if (mode === 'add' && !isInstalled()) { } @if (!isInstalled() && mode !== 'add') { - @if (item.type === ItemType.DEVICE) { - - } @else { - - } + } @if (isInstalled() && mode !== 'add') {