diff --git a/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java b/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java index 38764d08de..80192520ca 100644 --- a/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java +++ b/application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java @@ -38,10 +38,10 @@ import java.util.stream.Collectors; */ public class NetworkReceive implements Receive { - public final static String UNKNOWN_SOURCE = ""; - public final static int UNLIMITED = -1; - public final static int TB_MAX_REQUESTED_BUFFER_SIZE = 100 * 1024 * 1024; - public final static int TB_LOG_REQUESTED_BUFFER_SIZE = 10 * 1024 * 1024; + public static final String UNKNOWN_SOURCE = ""; + public static final int UNLIMITED = -1; + public static final int TB_MAX_REQUESTED_BUFFER_SIZE = 100 * 1024 * 1024; + public static final int TB_LOG_REQUESTED_BUFFER_SIZE = 10 * 1024 * 1024; private static final Logger log = LoggerFactory.getLogger(NetworkReceive.class); private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); @@ -54,27 +54,16 @@ public class NetworkReceive implements Receive { public NetworkReceive(String source, ByteBuffer buffer) { - this.source = source; + this(TB_MAX_REQUESTED_BUFFER_SIZE, source); this.buffer = buffer; - this.size = null; - this.maxSize = TB_MAX_REQUESTED_BUFFER_SIZE; - this.memoryPool = MemoryPool.NONE; } public NetworkReceive(String source) { - this.source = source; - this.size = ByteBuffer.allocate(4); - this.buffer = null; - this.maxSize = TB_MAX_REQUESTED_BUFFER_SIZE; - this.memoryPool = MemoryPool.NONE; + this(TB_MAX_REQUESTED_BUFFER_SIZE, source); } public NetworkReceive(int maxSize, String source) { - this.source = source; - this.size = ByteBuffer.allocate(4); - this.buffer = null; - this.maxSize = getMaxSize(maxSize); - this.memoryPool = MemoryPool.NONE; + this(maxSize, source, MemoryPool.NONE); } public NetworkReceive(int maxSize, String source, MemoryPool memoryPool) { diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 87d5c8a63a..253169a51d 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -23,7 +23,7 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import jakarta.annotation.Nullable; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.LinkedHashMapRemoveEldest; import org.thingsboard.server.actors.ActorSystemContext; diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java index 8f0a2fb3cd..8436e8fe35 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java @@ -19,7 +19,7 @@ import io.swagger.v3.oas.annotations.Parameter; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.annotation.AuthenticationPrincipal; diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 680633e103..63a435e6f1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -21,14 +21,11 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -48,7 +45,6 @@ import org.thingsboard.server.common.data.EventInfo; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.exception.ThingsboardException; -import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; @@ -56,7 +52,6 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageDataIterableByTenant; import org.thingsboard.server.common.data.page.PageLink; -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.rule.DefaultRuleChainCreateRequest; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainData; diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java index 289d6b2058..0c3146a6c6 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java index 9cc7416e34..36c2d91b8e 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.notification.rule.trigger.config.Alarm import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType; import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentTrigger; -import static org.apache.commons.collections.CollectionUtils.isEmpty; +import static org.apache.commons.collections4.CollectionUtils.isEmpty; import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains; @Service diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java index 392f68dc9e..bd2bccecb2 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.notification.rule.trigger.config.Notif import org.thingsboard.server.common.data.notification.rule.trigger.AlarmCommentTrigger; import org.thingsboard.server.dao.entity.EntityService; -import static org.apache.commons.collections.CollectionUtils.isEmpty; +import static org.apache.commons.collections4.CollectionUtils.isEmpty; import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains; @Service diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java index 99d58d40a9..b9047cac6b 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.notification.rule.trigger.config.Alarm import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmNotificationRuleTriggerConfig.ClearRule; import org.thingsboard.server.common.data.notification.rule.trigger.config.NotificationRuleTriggerType; -import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.thingsboard.server.common.data.util.CollectionsUtil.emptyOrContains; @Service diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java index 7380b8857a..e2d5484f59 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.notification.rule.trigger; import lombok.RequiredArgsConstructor; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.id.DeviceId; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeCommunicationFailureTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeCommunicationFailureTriggerProcessor.java index 38d8ae9805..2bc9a65cb2 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeCommunicationFailureTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeCommunicationFailureTriggerProcessor.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.notification.rule.trigger; import lombok.RequiredArgsConstructor; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.notification.info.EdgeCommunicationFailureNotificationInfo; import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeConnectionTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeConnectionTriggerProcessor.java index ed1ee74622..61b5c8ed56 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeConnectionTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeConnectionTriggerProcessor.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.notification.rule.trigger; import lombok.RequiredArgsConstructor; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.notification.info.EdgeConnectionNotificationInfo; import org.thingsboard.server.common.data.notification.info.RuleOriginatedNotificationInfo; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java index e1db043188..24000760b5 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java @@ -27,7 +27,7 @@ import org.thingsboard.server.dao.entity.EntityCountService; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.dao.tenant.TenantService; -import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; @Service @RequiredArgsConstructor diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java index 4c92e9b92b..c17805e1b6 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.notification.rule.trigger; import lombok.RequiredArgsConstructor; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.stereotype.Service; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DashboardExportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DashboardExportService.java index 8acb8990b8..3b2cb626ac 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DashboardExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DashboardExportService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.sync.ie.exporting.impl; import com.fasterxml.jackson.databind.JsonNode; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Dashboard; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java index 22ab41dd8a..4e0fdc33b8 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java @@ -16,7 +16,7 @@ package org.thingsboard.server.service.sync.ie.importing.impl; import lombok.RequiredArgsConstructor; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; diff --git a/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java b/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java index 424f739377..e41d1821c1 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java @@ -24,7 +24,7 @@ import com.google.common.util.concurrent.MoreExecutors; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.socket.CloseStatus; 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 cc5e5d5057..a87ab737e8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeEventControllerTest.java @@ -28,7 +28,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; -import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.edge.Edge; @@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.edge.EdgeEventDao; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; @@ -89,21 +90,22 @@ public class EdgeEventControllerTest extends AbstractControllerTest { Edge edge = constructEdge("TestEdge", "default"); edge = doPost("/api/edge", edge, Edge.class); + final EdgeId edgeId = edge.getId(); + + awaitForEdgeTemplateRootRuleChainToAssignToEdge(edgeId); + // simulate edge activation ObjectNode attributes = JacksonUtil.newObjectNode(); attributes.put("active", true); - doPost("/api/plugins/telemetry/EDGE/" + edge.getId() + "/attributes/" + DataConstants.SERVER_SCOPE, attributes); + doPost("/api/plugins/telemetry/EDGE/" + edge.getId() + "/attributes/" + AttributeScope.SERVER_SCOPE, attributes); Device device = constructDevice("TestDevice", "default"); Device savedDevice = doPost("/api/device", device, Device.class); - - final EdgeId edgeId = edge.getId(); - doPost("/api/edge/" + edgeId.toString() + "/device/" + savedDevice.getId().toString(), Device.class); + doPost("/api/edge/" + edgeId + "/device/" + savedDevice.getId(), Device.class); Asset asset = constructAsset("TestAsset", "default"); Asset savedAsset = doPost("/api/asset", asset, Asset.class); - - doPost("/api/edge/" + edgeId.toString() + "/asset/" + savedAsset.getId().toString(), Asset.class); + doPost("/api/edge/" + edgeId + "/asset/" + savedAsset.getId(), Asset.class); EntityRelation relation = new EntityRelation(savedAsset.getId(), savedDevice.getId(), EntityRelation.CONTAINS_TYPE); @@ -114,31 +116,12 @@ public class EdgeEventControllerTest extends AbstractControllerTest { awaitForNumberOfEdgeEvents(edgeId, 3); List edgeEvents = findEdgeEvents(edgeId); - Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.DEVICE)); // TestDevice - Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.ASSET)); // TestAsset + Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.DEVICE)); + Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.ASSET)); Assert.assertTrue(popEdgeEvent(edgeEvents, EdgeEventType.RELATION)); Assert.assertTrue(edgeEvents.isEmpty()); } - private boolean popEdgeEvent(List edgeEvents, EdgeEventType edgeEventType) { - for (EdgeEvent edgeEvent : edgeEvents) { - if (edgeEventType.equals(edgeEvent.getType())) { - edgeEvents.remove(edgeEvent); - return true; - } - } - return false; - } - - private void awaitForNumberOfEdgeEvents(EdgeId edgeId, int expectedNumber) { - Awaitility.await() - .atMost(30, TimeUnit.SECONDS) - .until(() -> { - List edgeEvents = findEdgeEvents(edgeId); - return edgeEvents.size() == expectedNumber; - }); - } - @Test public void saveEdgeEvent_thenCreatePartitionIfNotExist() { reset(partitioningRepository); @@ -167,12 +150,46 @@ public class EdgeEventControllerTest extends AbstractControllerTest { }); } + private boolean popEdgeEvent(List edgeEvents, EdgeEventType edgeEventType) { + for (EdgeEvent edgeEvent : edgeEvents) { + if (edgeEventType.equals(edgeEvent.getType())) { + edgeEvents.remove(edgeEvent); + return true; + } + } + return false; + } + + private void awaitForNumberOfEdgeEvents(EdgeId edgeId, int expectedNumber) { + Awaitility.await() + .atMost(TIMEOUT, TimeUnit.SECONDS) + .until(() -> { + List edgeEvents = findEdgeEvents(edgeId); + return edgeEvents.size() == expectedNumber; + }); + } + private List findEdgeEvents(EdgeId edgeId) throws Exception { - return doGetTypedWithTimePageLink("/api/edge/" + edgeId.toString() + "/events?", + return doGetTypedWithTimePageLink("/api/edge/" + edgeId + "/events?", new TypeReference>() { }, new TimePageLink(10)).getData(); } + private void awaitForEdgeTemplateRootRuleChainToAssignToEdge(EdgeId edgeId) { + Awaitility.await() + .atMost(TIMEOUT, TimeUnit.SECONDS) + .until(() -> { + List ruleChains = getEdgeRuleChains(edgeId); + return ruleChains.size() == 1; + }); + } + + private List getEdgeRuleChains(EdgeId edgeId) throws Exception { + return doGetTypedWithTimePageLink("/api/edge/" + edgeId + "/ruleChains?", + new TypeReference>() { + }, new TimePageLink(10)).getData(); + } + private Device constructDevice(String name, String type) { Device device = new Device(); device.setName(name); 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 060af9eac1..4bb8058e7f 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 @@ -523,18 +523,17 @@ public class NotificationApiTest extends AbstractNotificationApiTest { @Test public void testNotificationRequestStats() throws Exception { - wsClient.subscribeForUnreadNotifications(10); - wsClient.waitForReply(true); - - wsClient.registerWaitForUpdate(); NotificationTarget notificationTarget = createNotificationTarget(customerUserId); - NotificationRequest notificationRequest = submitNotificationRequest(notificationTarget.getId(), "Test :)", NotificationDeliveryMethod.WEB); - wsClient.waitForUpdate(); - await().atMost(2, TimeUnit.SECONDS) - .until(() -> findNotificationRequest(notificationRequest.getId()).isSent()); - NotificationRequestStats stats = getStats(notificationRequest.getId()); + NotificationRequest notificationRequest = submitNotificationRequest(notificationTarget.getId(), "Test :)", NotificationDeliveryMethod.WEB); + NotificationRequestStats stats = awaitNotificationRequest(notificationRequest.getId()); assertThat(stats.getSent().get(NotificationDeliveryMethod.WEB)).hasValue(1); + + doDelete("/api/user/mobile/session").andExpect(status().isOk()); + notificationRequest = submitNotificationRequest(notificationTarget.getId(), "Test", NotificationDeliveryMethod.MOBILE_APP); + stats = awaitNotificationRequest(notificationRequest.getId()); + assertThat(stats.getErrors().get(NotificationDeliveryMethod.MOBILE_APP)).hasSize(1); + assertThat(stats.getTotalErrors()).hasValue(1); } @Test 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 96e3e4732e..1ecae638a6 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 @@ -106,8 +106,11 @@ public class NotificationApiWsClient extends TbTestWebSocketClient { } } } else if (updateType == CmdUpdateType.NOTIFICATIONS_COUNT) { - lastCountUpdate = JacksonUtil.treeToValue(update, UnreadNotificationsCountUpdate.class); - unreadCount = lastCountUpdate.getTotalUnreadCount(); + UnreadNotificationsCountUpdate countUpdate = JacksonUtil.treeToValue(update, UnreadNotificationsCountUpdate.class); + if (lastCountUpdate == null || countUpdate.getSequenceNumber() > lastCountUpdate.getSequenceNumber()) { + lastCountUpdate = countUpdate; + unreadCount = lastCountUpdate.getTotalUnreadCount(); + } } super.onMessage(s); } diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java index 9ac2d5fc11..a1bf7932e9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java @@ -34,8 +34,6 @@ import static org.mockito.Mockito.spy; @DaoSqlTest public class CoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributesIntegrationTest { - CoapTransportResource coapTransportResource; - @Autowired DefaultCoapServerService defaultCoapServerService; @@ -44,10 +42,6 @@ public class CoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributes @Before public void beforeTest() throws Exception { - Resource api = defaultCoapServerService.getCoapServer().getRoot().getChild("api"); - coapTransportResource = spy( (CoapTransportResource) api.getChild("v1") ); - api.delete(api.getChild("v1") ); - api.add(coapTransportResource); CoapTestConfigProperties configProperties = CoapTestConfigProperties.builder() .deviceName("Test Subscribe to attribute updates") .build(); diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index dc4a829504..1ea925804f 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -61,7 +61,7 @@ jakarta.annotation-api - com.github.fge + com.github.java-json-tools json-schema-validator diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index dbc9251ba3..0aad8d7183 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -57,7 +57,7 @@ jakarta.annotation-api - com.github.fge + com.github.java-json-tools json-schema-validator diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java index 53b5d2ec63..b529edeb0c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DataConstants.java @@ -44,6 +44,8 @@ public class DataConstants { public static final String EDGE_ID = "edgeId"; public static final String DEVICE_ID = "deviceId"; public static final String GATEWAY_PARAMETER = "gateway"; + + public static final String OVERWRITE_ACTIVITY_TIME_PARAMETER = "overwriteActivityTime"; public static final String COAP_TRANSPORT_NAME = "COAP"; public static final String LWM2M_TRANSPORT_NAME = "LWM2M"; public static final String MQTT_TRANSPORT_NAME = "MQTT"; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java index 2bd9c526fd..e9e22e81ee 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java @@ -34,7 +34,6 @@ public class NotificationRequestStats { @JsonIgnore private final AtomicInteger totalSent; private final Map> errors; - @JsonIgnore private final AtomicInteger totalErrors; private String error; @JsonIgnore @@ -51,11 +50,19 @@ public class NotificationRequestStats { @JsonCreator public NotificationRequestStats(@JsonProperty("sent") Map sent, @JsonProperty("errors") Map> errors, + @JsonProperty("totalErrors") Integer totalErrors, @JsonProperty("error") String error) { this.sent = sent; this.totalSent = null; this.errors = errors; - this.totalErrors = null; + if (totalErrors == null) { + if (errors != null) { + totalErrors = errors.values().stream().mapToInt(Map::size).sum(); + } else { + totalErrors = 0; + } + } + this.totalErrors = new AtomicInteger(totalErrors); this.error = error; this.processedRecipients = Collections.emptyMap(); } @@ -73,7 +80,10 @@ public class NotificationRequestStats { if (errorMessage == null) { errorMessage = error.getClass().getSimpleName(); } - errors.computeIfAbsent(deliveryMethod, k -> new ConcurrentHashMap<>()).put(recipient.getTitle(), errorMessage); + Map errors = this.errors.computeIfAbsent(deliveryMethod, k -> new ConcurrentHashMap<>()); + if (errors.size() < 100) { + errors.put(recipient.getTitle(), errorMessage); + } totalErrors.incrementAndGet(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java index 79556080ff..0956c256a3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import lombok.ToString; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; @@ -48,6 +49,7 @@ public class UserSettings implements Serializable { private transient JsonNode settings; @JsonIgnore + @ToString.Exclude private byte[] settingsBytes; public JsonNode getSettings() { diff --git a/common/message/pom.xml b/common/message/pom.xml index e6b61916b0..cb7e2d078a 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -42,7 +42,7 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on org.slf4j @@ -61,7 +61,7 @@ logback-classic - com.github.vladimir-bukhtoyarov + com.bucket4j bucket4j-core diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java b/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java index df5a4a728c..27c9bdecf8 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.msg; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.crypto.digests.SHA3Digest; -import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.bouncycastle.pqc.legacy.math.linearalgebra.ByteUtils; /** * @author Valerii Sosliuk diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimits.java b/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimits.java index d93f8982c6..9ed1ac4384 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimits.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimits.java @@ -16,7 +16,7 @@ package org.thingsboard.server.common.msg.tools; import io.github.bucket4j.Bandwidth; -import io.github.bucket4j.Bucket4j; +import io.github.bucket4j.Bucket; import io.github.bucket4j.Refill; import io.github.bucket4j.local.LocalBucket; import io.github.bucket4j.local.LocalBucketBuilder; @@ -38,7 +38,7 @@ public class TbRateLimits { } public TbRateLimits(String limitsConfiguration, boolean refillIntervally) { - LocalBucketBuilder builder = Bucket4j.builder(); + LocalBucketBuilder builder = Bucket.builder(); boolean initialized = false; for (String limitSrc : limitsConfiguration.split(",")) { long capacity = Long.parseLong(limitSrc.split(":")[0]); diff --git a/common/message/src/test/java/org/thingsboard/server/common/msg/EncryptionUtilTest.java b/common/message/src/test/java/org/thingsboard/server/common/msg/EncryptionUtilTest.java new file mode 100644 index 0000000000..d67fe74fea --- /dev/null +++ b/common/message/src/test/java/org/thingsboard/server/common/msg/EncryptionUtilTest.java @@ -0,0 +1,30 @@ +/** + * Copyright © 2016-2024 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. + */ +package org.thingsboard.server.common.msg; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class EncryptionUtilTest { + + @Test + void getSha3Hash256Size() { + assertThat(EncryptionUtil.getSha3Hash("ThingsBoard")) + .isEqualTo("281c7ba06d0ac2ff651fa968572f26a38c96225ea54644522837b54b9c6144f7"); + } + +} diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index 8360111a54..b48cb39ca0 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -45,6 +45,7 @@ import io.netty.util.concurrent.GenericFutureListener; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.ResponseCode; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; @@ -64,7 +65,6 @@ import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; @@ -323,6 +323,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement if (checkConnected(ctx, msg)) { ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0))); transportService.recordActivity(deviceSessionCtx.getSessionInfo()); + if (gatewaySessionHandler != null) { + gatewaySessionHandler.onGatewayPing(); + } } break; case DISCONNECT: @@ -1080,12 +1083,15 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement try { JsonNode infoNode = context.getMapper().readTree(device.getAdditionalInfo()); if (infoNode != null) { - JsonNode gatewayNode = infoNode.get("gateway"); + JsonNode gatewayNode = infoNode.get(DataConstants.GATEWAY_PARAMETER); if (gatewayNode != null && gatewayNode.asBoolean()) { - gatewaySessionHandler = new GatewaySessionHandler(deviceSessionCtx, sessionId); - if (infoNode.has(DefaultTransportService.OVERWRITE_ACTIVITY_TIME) && infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).isBoolean()) { - sessionMetaData.setOverwriteActivityTime(infoNode.get(DefaultTransportService.OVERWRITE_ACTIVITY_TIME).asBoolean()); + boolean overwriteDevicesActivity = false; + if (infoNode.has(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER) + && infoNode.get(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER).isBoolean()) { + overwriteDevicesActivity = infoNode.get(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER).asBoolean(); + sessionMetaData.setOverwriteActivityTime(overwriteDevicesActivity); } + gatewaySessionHandler = new GatewaySessionHandler(deviceSessionCtx, sessionId, overwriteDevicesActivity); } } } catch (IOException e) { @@ -1099,7 +1105,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement SparkplugTopic sparkplugTopicNode = validatedSparkplugTopicConnectedNode(connectMessage); if (sparkplugTopicNode != null) { SparkplugBProto.Payload sparkplugBProtoNode = SparkplugBProto.Payload.parseFrom(connectMessage.payload().willMessageInBytes()); - sparkplugSessionHandler = new SparkplugNodeSessionHandler(this, deviceSessionCtx, sessionId, sparkplugTopicNode); + sparkplugSessionHandler = new SparkplugNodeSessionHandler(this, deviceSessionCtx, sessionId, true, sparkplugTopicNode); sparkplugSessionHandler.onAttributesTelemetryProto(0, sparkplugBProtoNode, sparkplugTopicNode); sessionMetaData.setOverwriteActivityTime(true); } else { @@ -1354,6 +1360,9 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @Override public void onDeviceUpdate(TransportProtos.SessionInfoProto sessionInfo, Device device, Optional deviceProfileOpt) { deviceSessionCtx.onDeviceUpdate(sessionInfo, device, deviceProfileOpt); + if (gatewaySessionHandler != null) { + gatewaySessionHandler.onDeviceUpdate(sessionInfo, device, deviceProfileOpt); + } } @Override diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java index 11f983ee3d..d033774e93 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java @@ -16,6 +16,7 @@ package org.thingsboard.server.transport.mqtt.session; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -32,17 +33,21 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.mqtt.MqttMessage; import io.netty.handler.codec.mqtt.MqttPublishMessage; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.util.CollectionUtils; import org.springframework.util.ConcurrentReferenceHashMap; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.ProtoConverter; import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.adaptor.AdaptorException; -import org.thingsboard.server.common.adaptor.JsonConverter; -import org.thingsboard.server.common.adaptor.ProtoConverter; import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.gen.transport.TransportApiProtos; @@ -64,6 +69,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -101,7 +107,11 @@ public abstract class AbstractGatewaySessionHandler createWeakMap() { @@ -164,6 +175,12 @@ public abstract class AbstractGatewaySessionHandler transportService.recordActivity(deviceSessionCtx.getSessionInfo())); + } + } + public void onDevicesDisconnect() { devices.forEach(this::deregisterSession); } @@ -221,6 +238,14 @@ public abstract class AbstractGatewaySessionHandler deviceProfileOpt) { + log.trace("[{}][{}] onDeviceUpdate: [{}]", gateway.getTenantId(), gateway.getDeviceId(), device); + JsonNode deviceAdditionalInfo = device.getAdditionalInfo(); + if (deviceAdditionalInfo.has(DataConstants.GATEWAY_PARAMETER) && deviceAdditionalInfo.has(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER)) { + overwriteDevicesActivity = deviceAdditionalInfo.get(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER).asBoolean(); + } + } + ListenableFuture onDeviceConnect(String deviceName, String deviceType) { T result = devices.get(deviceName); if (result == null) { diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java index 9ccc88aa82..9aa228afff 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java @@ -25,10 +25,10 @@ import java.util.UUID; /** * Created by nickAS21 on 26.12.22 */ -public class GatewaySessionHandler extends AbstractGatewaySessionHandler { +public class GatewaySessionHandler extends AbstractGatewaySessionHandler { - public GatewaySessionHandler(DeviceSessionCtx deviceSessionCtx, UUID sessionId) { - super(deviceSessionCtx, sessionId); + public GatewaySessionHandler(DeviceSessionCtx deviceSessionCtx, UUID sessionId, boolean overwriteDevicesActivity) { + super(deviceSessionCtx, sessionId, overwriteDevicesActivity); } public void onDeviceConnect(MqttPublishMessage mqttMsg) throws AdaptorException { diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java index 05658fe97a..1f389fced1 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java @@ -73,8 +73,8 @@ public class SparkplugNodeSessionHandler extends AbstractGatewaySessionHandler(); 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 bd1ddd2d54..158acc2ce2 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 @@ -15,15 +15,101 @@ */ package org.thingsboard.server.transport.mqtt.session; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.util.ConcurrentReferenceHashMap; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.transport.TransportService; +import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; +import org.thingsboard.server.transport.mqtt.MqttTransportContext; + +import java.lang.reflect.Field; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.willCallRealMethod; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doNothing; +@ExtendWith(MockitoExtension.class) public class GatewaySessionHandlerTest { + @Mock + private TransportService transportService; + + @Mock + private DeviceSessionCtx deviceSessionCtx; + + @Mock + private MqttTransportContext transportContext; + + private GatewaySessionHandler handler; + + @BeforeEach + public void setup() { + lenient().when(deviceSessionCtx.getSessionId()).thenReturn(UUID.randomUUID()); + lenient().doNothing().when(transportService).recordActivity(any()); + lenient().when(transportContext.getTransportService()).thenReturn(transportService); + lenient().when(deviceSessionCtx.getContext()).thenReturn(transportContext); + handler = new GatewaySessionHandler(deviceSessionCtx, UUID.randomUUID(), true); + lenient().when(handler.getNodeId()).thenReturn("nodeId"); + } + + @Test + public void shouldRecordActivityWhenOnGatewayPing() throws Exception { + // Given + ConcurrentHashMap devices = new ConcurrentHashMap<>(); + TransportDeviceInfo deviceInfo = new TransportDeviceInfo(); + deviceInfo.setDeviceId(new DeviceId(UUID.randomUUID())); + deviceInfo.setTenantId(new TenantId(UUID.randomUUID())); + deviceInfo.setCustomerId(new CustomerId(UUID.randomUUID())); + deviceInfo.setDeviceName("device1"); + deviceInfo.setDeviceType("default"); + deviceInfo.setDeviceProfileId(new DeviceProfileId(UUID.randomUUID())); + deviceInfo.setAdditionalInfo("{\"gateway\": true, \"overwriteDeviceActivity\": true}"); + lenient().when(deviceSessionCtx.getDeviceInfo()).thenReturn(deviceInfo); + GatewayDeviceSessionContext gatewayDeviceSessionContext = new GatewayDeviceSessionContext(handler, deviceInfo, null, null, transportService); + devices.put("device1", gatewayDeviceSessionContext); + lenient().when(handler.getNodeId()).thenReturn("nodeId"); + Field devicesField = AbstractGatewaySessionHandler.class.getDeclaredField("devices"); + devicesField.setAccessible(true); + devicesField.set(handler, devices); + + // When + handler.onGatewayPing(); + + // Then + verify(transportService).recordActivity(gatewayDeviceSessionContext.getSessionInfo()); + } + + @Test + public void shouldNotRecordActivityWhenNoDevicesOnGatewayPing() throws Exception { + // Given + ConcurrentHashMap devices = new ConcurrentHashMap<>(); + Field devicesField = AbstractGatewaySessionHandler.class.getDeclaredField("devices"); + devicesField.setAccessible(true); + devicesField.set(handler, devices); + + // When + handler.onGatewayPing(); + + // Then + verify(transportService, never()).recordActivity(any()); + } + @Test public void givenGatewaySessionHandler_WhenCreateWeakMap_thenConcurrentReferenceHashMapClass() { GatewaySessionHandler gsh = mock(GatewaySessionHandler.class); diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 255b9ad8e4..4e9ad1ba31 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -127,11 +127,11 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index 8854ad3a7d..6280f09cfd 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.transport.service; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; @@ -131,7 +132,6 @@ import java.util.stream.Collectors; @TbTransportComponent public class DefaultTransportService extends TransportActivityManager implements TransportService { - public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime"; public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_OPEN = TransportProtos.SessionEventMsg.newBuilder() .setSessionType(TransportProtos.SessionType.ASYNC) .setEvent(TransportProtos.SessionEvent.OPEN).build(); @@ -1042,11 +1042,12 @@ public class DefaultTransportService extends TransportActivityManager implements .setDeviceProfileIdLSB(deviceProfileIdLSB) .setDeviceName(device.getName()) .setDeviceType(device.getType()).build(); - if (device.getAdditionalInfo().has("gateway") - && device.getAdditionalInfo().get("gateway").asBoolean() - && device.getAdditionalInfo().has(OVERWRITE_ACTIVITY_TIME) - && device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).isBoolean()) { - md.setOverwriteActivityTime(device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).asBoolean()); + JsonNode deviceAdditionalInfo = device.getAdditionalInfo(); + if (deviceAdditionalInfo.has(DataConstants.GATEWAY_PARAMETER) + && deviceAdditionalInfo.get(DataConstants.GATEWAY_PARAMETER).asBoolean() + && deviceAdditionalInfo.has(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER) + && deviceAdditionalInfo.get(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER).isBoolean()) { + md.setOverwriteActivityTime(deviceAdditionalInfo.get(DataConstants.OVERWRITE_ACTIVITY_TIME_PARAMETER).asBoolean()); } md.setSessionInfo(newSessionInfo); transportCallbackExecutor.submit(() -> md.getListener().onDeviceUpdate(newSessionInfo, device, Optional.ofNullable(newDeviceProfile))); diff --git a/common/util/pom.xml b/common/util/pom.xml index 1952e5a7ad..143a34e6c9 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -38,11 +38,11 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on org.springframework @@ -104,6 +104,10 @@ com.fasterxml.jackson.datatype jackson-datatype-jsr310 + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + 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 6817ec71f0..ff5716a361 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 @@ -28,6 +28,8 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; @@ -38,6 +40,8 @@ import java.io.File; import java.io.IOException; import java.io.Reader; import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; @@ -54,22 +58,30 @@ import java.util.regex.Pattern; @Slf4j public class JacksonUtil { - public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + public static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder() + .addModule(new Jdk8Module()) + .build(); public static final ObjectMapper PRETTY_SORTED_JSON_MAPPER = JsonMapper.builder() + .addModule(new Jdk8Module()) .enable(SerializationFeature.INDENT_OUTPUT) .configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true) .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) .build(); public static ObjectMapper ALLOW_UNQUOTED_FIELD_NAMES_MAPPER = JsonMapper.builder() + .addModule(new Jdk8Module()) .configure(JsonWriteFeature.QUOTE_FIELD_NAMES.mappedFeature(), false) .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) .build(); public static final ObjectMapper IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER = JsonMapper.builder() + .addModule(new Jdk8Module()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .build(); public static ObjectMapper getObjectMapperWithJavaTimeModule() { - return new ObjectMapper().registerModule(new JavaTimeModule()); + return JsonMapper.builder() + .addModule(new Jdk8Module()) + .addModule(new JavaTimeModule()) + .build(); } public static T convertValue(Object fromValue, Class toValueType) { @@ -124,7 +136,7 @@ public class JacksonUtil { try { return bytes != null ? OBJECT_MAPPER.readValue(bytes, clazz) : null; } catch (IOException e) { - throw new IllegalArgumentException("The given string value cannot be transformed to Json object: " + Arrays.toString(bytes), e); + throw new IllegalArgumentException("The given byte[] value cannot be transformed to Json object:" + Arrays.toString(bytes), e); } } @@ -152,6 +164,15 @@ public class JacksonUtil { } } + public static String writeValueAsString(Object value) { + try { + return OBJECT_MAPPER.writeValueAsString(value); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("The given Json object value: " + + value + " cannot be transformed to a String", e); + } + } + public static String toPrettyString(Object o) { try { return PRETTY_SORTED_JSON_MAPPER.writeValueAsString(o); @@ -197,6 +218,38 @@ public class JacksonUtil { } } + public static T readValue(String file, CollectionType clazz) { + try { + return OBJECT_MAPPER.readValue(file, clazz); + } catch (IOException e) { + throw new IllegalArgumentException("Can't read file: " + file, e); + } + } + + public static T readValue(File file, TypeReference clazz) { + try { + return OBJECT_MAPPER.readValue(file, clazz); + } catch (IOException e) { + throw new IllegalArgumentException("Can't read file: " + file, e); + } + } + + public static T readValue(File file, Class clazz) { + try { + return OBJECT_MAPPER.readValue(file, clazz); + } catch (IOException e) { + throw new IllegalArgumentException("Can't read file: " + file, e); + } + } + + public static JsonNode toJsonNode(Path file) { + try { + return OBJECT_MAPPER.readTree(Files.readAllBytes(file)); + } catch (IOException e) { + throw new IllegalArgumentException("Can't read file: " + file, e); + } + } + public static JsonNode toJsonNode(File value) { try { return value != null ? OBJECT_MAPPER.readTree(value) : null; @@ -240,7 +293,6 @@ public class JacksonUtil { } } - public static JsonNode getSafely(JsonNode node, String... path) { if (node == null) { return null; diff --git a/common/util/src/test/java/org/thingsboard/common/util/JacksonUtilTest.java b/common/util/src/test/java/org/thingsboard/common/util/JacksonUtilTest.java index dcddc6e07a..f864875d37 100644 --- a/common/util/src/test/java/org/thingsboard/common/util/JacksonUtilTest.java +++ b/common/util/src/test/java/org/thingsboard/common/util/JacksonUtilTest.java @@ -25,8 +25,13 @@ import org.junit.jupiter.params.provider.ValueSource; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; +import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; + public class JacksonUtilTest { @Test @@ -69,4 +74,13 @@ public class JacksonUtilTest { Assertions.assertNotNull(serialized); Assertions.assertEquals(original, JacksonUtil.toPlainText(serialized)); } -} + + @Test + public void optionalMappingJDK8ModuleTest() { + // To address the issue: Java 8 optional type `java.util.Optional` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jdk8" to enable handling + assertThat(JacksonUtil.writeValueAsString(Optional.of("hello"))).isEqualTo("\"hello\""); + assertThat(JacksonUtil.writeValueAsString(List.of(Optional.of("abc")))).isEqualTo("[\"abc\"]"); + assertThat(JacksonUtil.writeValueAsString(Set.of(Optional.empty()))).isEqualTo("[null]"); + } + +} \ No newline at end of file diff --git a/dao/pom.xml b/dao/pom.xml index ab62d8f013..061c130a69 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -81,7 +81,7 @@ org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on org.springframework.boot @@ -113,8 +113,8 @@ commons-lang3 - commons-collections - commons-collections + org.apache.commons + commons-collections4 com.fasterxml.jackson.core @@ -190,7 +190,7 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on org.springframework.boot @@ -222,7 +222,7 @@ org.elasticsearch.client - rest + elasticsearch-rest-client org.eclipse.leshan @@ -238,7 +238,7 @@ io.hypersistence - hypersistence-utils-hibernate-62 + hypersistence-utils-hibernate-63 org.apache.xmlgraphics diff --git a/dao/src/main/java/org/thingsboard/server/dao/ThingsboardPostgreSQLDialect.java b/dao/src/main/java/org/thingsboard/server/dao/ThingsboardPostgreSQLDialect.java index 8acb13b5bb..5da1c32616 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/ThingsboardPostgreSQLDialect.java +++ b/dao/src/main/java/org/thingsboard/server/dao/ThingsboardPostgreSQLDialect.java @@ -15,23 +15,26 @@ */ package org.thingsboard.server.dao; +import lombok.extern.slf4j.Slf4j; import org.hibernate.boot.model.FunctionContributions; import org.hibernate.dialect.PostgreSQLDialect; import org.hibernate.query.sqm.function.SqmFunctionRegistry; import org.hibernate.type.BasicTypeRegistry; import org.hibernate.type.StandardBasicTypes; +@Slf4j public class ThingsboardPostgreSQLDialect extends PostgreSQLDialect { @Override public void initializeFunctionRegistry(FunctionContributions functionContributions) { + log.trace("initializeFunctionRegistry [{}]", functionContributions); super.initializeFunctionRegistry(functionContributions); BasicTypeRegistry basicTypeRegistry = functionContributions.getTypeConfiguration().getBasicTypeRegistry(); SqmFunctionRegistry functionRegistry = functionContributions.getFunctionRegistry(); functionRegistry.registerPattern( "ilike", - "(?1 ILIKE ?2)", + "(?1::text ILIKE ?2::text)", basicTypeRegistry.resolve(StandardBasicTypes.BOOLEAN)); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java b/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java index 4d2c10a7cd..5d143ef009 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java @@ -25,6 +25,7 @@ import org.apache.http.client.CredentialsProvider; import org.apache.http.entity.ContentType; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.nio.entity.NStringEntity; +import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseListener; import org.elasticsearch.client.RestClient; @@ -124,12 +125,10 @@ public class ElasticsearchAuditLogSink implements AuditLogSink { jsonContent, ContentType.APPLICATION_JSON); - restClient.performRequestAsync( - HttpMethod.POST.name(), - String.format("/%s/%s", getIndexName(auditLogEntry.getTenantId()), INDEX_TYPE), - Collections.emptyMap(), - entity, - responseListener); + Request request = new Request(HttpMethod.POST.name(),String.format("/%s/%s", getIndexName(auditLogEntry.getTenantId()), INDEX_TYPE)); + request.setEntity(entity); + + restClient.performRequestAsync(request, responseListener); } private String createElasticJsonRecord(AuditLog auditLog) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java index 90f54a316a..94c339335b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java @@ -52,7 +52,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; -import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; @Service @Slf4j diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java index 6535b54a2c..5bb7ae163e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.oauth2; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.BaseData; 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 8e1af4a531..ae3929f5fb 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 @@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.hibernate.exception.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; @@ -653,7 +653,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC @Override public RuleChain getEdgeTemplateRootRuleChain(TenantId tenantId) { - Validator.validateId(tenantId, "Incorrect tenant id for search request."); + Validator.validateId(tenantId, id -> INCORRECT_TENANT_ID + id); return ruleChainDao.findRootRuleChainByTenantIdAndType(tenantId.getId(), RuleChainType.EDGE); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java index 222aaa3eeb..9f1eda9528 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.service.validator; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index 83827973ba..735234ffaa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -57,7 +57,7 @@ public interface AlarmRepository extends JpaRepository { "AND (:endTime IS NULL OR (a.createdTime <= :endTime AND ea.createdTime <= :endTime)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true)) " @@ -74,7 +74,7 @@ public interface AlarmRepository extends JpaRepository { "AND (:endTime IS NULL OR (a.createdTime <= :endTime AND ea.createdTime <= :endTime)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true))") @@ -87,7 +87,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId, + @Param("assigneeId") UUID assigneeId, @Param("searchText") String searchText, Pageable pageable); @@ -106,7 +106,7 @@ public interface AlarmRepository extends JpaRepository { // "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true)) " @@ -127,7 +127,7 @@ public interface AlarmRepository extends JpaRepository { // "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true))") @@ -142,7 +142,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId, + @Param("assigneeId") UUID assigneeId, @Param("searchText") String searchText, Pageable pageable); @@ -153,7 +153,7 @@ public interface AlarmRepository extends JpaRepository { "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true)) ", @@ -165,7 +165,7 @@ public interface AlarmRepository extends JpaRepository { "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true))") @@ -176,7 +176,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId, + @Param("assigneeId") UUID assigneeId, @Param("searchText") String searchText, Pageable pageable); @@ -191,7 +191,7 @@ public interface AlarmRepository extends JpaRepository { // "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true)) ", @@ -207,7 +207,7 @@ public interface AlarmRepository extends JpaRepository { // "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true))") @@ -220,7 +220,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId, + @Param("assigneeId") UUID assigneeId, @Param("searchText") String searchText, Pageable pageable); @@ -231,7 +231,7 @@ public interface AlarmRepository extends JpaRepository { "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true)) " @@ -244,7 +244,7 @@ public interface AlarmRepository extends JpaRepository { "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true))") @@ -256,7 +256,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId, + @Param("assigneeId") UUID assigneeId, @Param("searchText") String searchText, Pageable pageable); @@ -271,7 +271,7 @@ public interface AlarmRepository extends JpaRepository { // "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true)) " @@ -288,7 +288,7 @@ public interface AlarmRepository extends JpaRepository { // "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId) " + "AND (:searchText IS NULL OR (ilike(a.type, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.severity, CONCAT('%', :searchText, '%')) = true " + " OR ilike(a.status, CONCAT('%', :searchText, '%')) = true))") @@ -302,7 +302,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId, + @Param("assigneeId") UUID assigneeId, @Param("searchText") String searchText, Pageable pageable); @@ -314,7 +314,7 @@ public interface AlarmRepository extends JpaRepository { "AND ea.entityType = :affectedEntityType " + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + - "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId))") + "AND (:assigneeId IS NULL OR a.assigneeId = :assigneeId)") Set findAlarmSeverities(@Param("tenantId") UUID tenantId, @Param("affectedEntityId") UUID affectedEntityId, @Param("affectedEntityType") String affectedEntityType, @@ -322,7 +322,7 @@ public interface AlarmRepository extends JpaRepository { @Param("clearFilter") boolean clearFilter, @Param("ackFilterEnabled") boolean ackFilterEnabled, @Param("ackFilter") boolean ackFilter, - @Param("assigneeId") String assigneeId); + @Param("assigneeId") UUID assigneeId); @Query("SELECT a.id FROM AlarmEntity a WHERE a.tenantId = :tenantId AND a.createdTime < :time AND a.endTs < :time") Page findAlarmsIdsByEndTsBeforeAndTenantId(@Param("time") Long time, @Param("tenantId") UUID tenantId, Pageable pageable); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index cbadbb4951..90a5b1f8d4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -154,7 +154,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - DaoUtil.getStringId(query.getAssigneeId()), + DaoUtil.getId(query.getAssigneeId()), query.getPageLink().getTextSearch(), DaoUtil.toPageable(query.getPageLink()) ) @@ -169,7 +169,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - DaoUtil.getStringId(query.getAssigneeId()), + DaoUtil.getId(query.getAssigneeId()), query.getPageLink().getTextSearch(), DaoUtil.toPageable(query.getPageLink()) ) @@ -191,7 +191,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - DaoUtil.getStringId(query.getAssigneeId()), + DaoUtil.getId(query.getAssigneeId()), query.getPageLink().getTextSearch(), DaoUtil.toPageable(query.getPageLink()) ) @@ -219,7 +219,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - DaoUtil.getStringId(query.getAssigneeId()), + DaoUtil.getId(query.getAssigneeId()), query.getPageLink().getTextSearch(), DaoUtil.toPageable(query.getPageLink()) ) @@ -236,7 +236,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - DaoUtil.getStringId(query.getAssigneeId()), + DaoUtil.getId(query.getAssigneeId()), query.getPageLink().getTextSearch(), DaoUtil.toPageable(query.getPageLink()) ) @@ -262,7 +262,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - DaoUtil.getStringId(query.getAssigneeId()), + DaoUtil.getId(query.getAssigneeId()), query.getPageLink().getTextSearch(), DaoUtil.toPageable(query.getPageLink()) ) @@ -281,7 +281,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId); + StringUtils.isNotBlank(assigneeId) ? UUID.fromString(assigneeId) : null); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java index bfc310cddd..289da44626 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java @@ -126,20 +126,20 @@ public interface DeviceRepository extends JpaRepository, Exp @Query("SELECT d FROM DeviceInfoEntity d " + "WHERE d.tenantId = :tenantId " + - "AND (:customerId IS NULL OR d.customerId = uuid(:customerId)) " + - "AND (:edgeId IS NULL OR d.id IN (SELECT re.toId FROM RelationEntity re WHERE re.toType = 'DEVICE' AND re.relationTypeGroup = 'EDGE' AND re.relationType = 'Contains' AND re.fromType = 'EDGE' AND re.fromId = uuid(:edgeId))) " + + "AND (:customerId IS NULL OR d.customerId = :customerId) " + + "AND (:edgeId IS NULL OR d.id IN (SELECT re.toId FROM RelationEntity re WHERE re.toType = 'DEVICE' AND re.relationTypeGroup = 'EDGE' AND re.relationType = 'Contains' AND re.fromType = 'EDGE' AND re.fromId = :edgeId)) " + "AND ((:deviceType) IS NULL OR d.type = :deviceType) " + - "AND (:deviceProfileId IS NULL OR d.deviceProfileId = uuid(:deviceProfileId)) " + + "AND (:deviceProfileId IS NULL OR d.deviceProfileId = :deviceProfileId) " + "AND ((:filterByActive) = FALSE OR d.active = :deviceActive) " + "AND (:textSearch IS NULL OR ilike(d.name, CONCAT('%', :textSearch, '%')) = true " + "OR ilike(d.label, CONCAT('%', :textSearch, '%')) = true " + "OR ilike(d.type, CONCAT('%', :textSearch, '%')) = true " + "OR ilike(d.customerTitle, CONCAT('%', :textSearch, '%')) = true)") Page findDeviceInfosByFilter(@Param("tenantId") UUID tenantId, - @Param("customerId") String customerId, - @Param("edgeId") String edgeId, + @Param("customerId") UUID customerId, + @Param("edgeId") UUID edgeId, @Param("deviceType") String type, - @Param("deviceProfileId") String deviceProfileId, + @Param("deviceProfileId") UUID deviceProfileId, @Param("filterByActive") boolean filterByActive, @Param("deviceActive") boolean active, @Param("textSearch") String textSearch, diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index 9aa9a48fab..64f37f3838 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -110,10 +110,10 @@ public class JpaDeviceDao extends JpaAbstractDao implement return DaoUtil.toPageData( deviceRepository.findDeviceInfosByFilter( filter.getTenantId().getId(), - DaoUtil.getStringId(filter.getCustomerId()), - DaoUtil.getStringId(filter.getEdgeId()), + DaoUtil.getId(filter.getCustomerId()), + DaoUtil.getId(filter.getEdgeId()), filter.getType(), - DaoUtil.getStringId(filter.getDeviceProfileId()), + DaoUtil.getId(filter.getDeviceProfileId()), filter.getActive() != null, Boolean.TRUE.equals(filter.getActive()), pageLink.getTextSearch(), diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java index 52a78c41fe..73b616e7ba 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java @@ -40,6 +40,7 @@ public class JpaUserSettingsDao extends JpaAbstractDaoListeningExecutorService i @Override public UserSettings save(TenantId tenantId, UserSettings userSettings) { + log.trace("save [{}][{}]", tenantId, userSettings); return DaoUtil.getData(userSettingsRepository.save(new UserSettingsEntity(userSettings))); } @@ -55,6 +56,7 @@ public class JpaUserSettingsDao extends JpaAbstractDaoListeningExecutorService i @Override public List findByTypeAndPath(TenantId tenantId, UserSettingsType type, String... path) { + log.trace("findByTypeAndPath [{}][{}][{}]", tenantId, type, path); return DaoUtil.convertDataList(userSettingsRepository.findByTypeAndPathExisting(type.name(), path)); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDaoTest.java index bf30ebb83b..2151f728d0 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDaoTest.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.sql.user; import com.datastax.oss.driver.api.core.uuid.Uuids; +import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -37,11 +38,14 @@ import org.thingsboard.server.dao.user.UserSettingsDao; import java.util.UUID; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.Index.atIndex; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; import static org.thingsboard.server.dao.service.AbstractServiceTest.SYSTEM_TENANT_ID; +@Slf4j public class JpaUserSettingsDaoTest extends AbstractJpaDaoTest { private UUID tenantId; @@ -77,6 +81,34 @@ public class JpaUserSettingsDaoTest extends AbstractJpaDaoTest { assertNull(retrievedUserSettings2); } + // If Hibernate fail to bind JSON path please check the hypersistence-utils-hibernate-XX artifact name and version in the dependency management + // Example: java.lang.ClassCastException: class [Ljava.lang.String; cannot be cast to class [B ([Ljava.lang.String; and [B are in module java.base of loader 'bootstrap') + @Test + public void testFindByTypeAndJsonPath() { + UserSettings userSettings = createUserSettings(user.getId()); + log.warn("userSettings {}", userSettings); + + userSettings.setSettings(JacksonUtil.toJsonNode("{\"text\":\"bla1\",\"sessions\":{\"tenantFcmToken\":{\"fcmTokenTimestamp\":0}}}")); + + userSettingsDao.save(SYSTEM_TENANT_ID, userSettings); + + assertThat(userSettingsDao.findByTypeAndPath(SYSTEM_TENANT_ID, UserSettingsType.GENERAL, "text")) + .isNotEmpty().hasSize(1).contains(userSettings, atIndex(0)); + + assertThat(userSettingsDao.findByTypeAndPath(SYSTEM_TENANT_ID, UserSettingsType.GENERAL, "sessions", "tenantFcmToken")) + .isNotEmpty().hasSize(1).contains(userSettings, atIndex(0)); + + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.GENERAL, "mistery")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.GENERAL, "text", "text")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.GENERAL, "text", "lvl2")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.MOBILE, "text")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.MOBILE, "sessions", "1")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.MOBILE, "text", "text")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.MOBILE, "")).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.MOBILE, null)).isEmpty(); + assertThat(userSettingsDao.findByTypeAndPath(user.getTenantId(), UserSettingsType.MOBILE)).isEmpty(); + } + private UserSettings createUserSettings(UserId userId) { UserSettings userSettings = new UserSettings(); userSettings.setType(UserSettingsType.GENERAL); diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index cbbd76a1f6..f1b7525438 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -85,7 +85,7 @@ org.hamcrest - hamcrest-all + hamcrest test diff --git a/msa/monitoring/docker/start-tb-monitoring.sh b/msa/monitoring/docker/start-tb-monitoring.sh index 692719b1f0..026fa58888 100755 --- a/msa/monitoring/docker/start-tb-monitoring.sh +++ b/msa/monitoring/docker/start-tb-monitoring.sh @@ -28,4 +28,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.monitoring.ThingsboardMonitoringApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=$CONF_FOLDER/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/msa/tb-node/docker/start-tb-node.sh b/msa/tb-node/docker/start-tb-node.sh index 76ed35cc7c..c164954a82 100755 --- a/msa/tb-node/docker/start-tb-node.sh +++ b/msa/tb-node/docker/start-tb-node.sh @@ -41,7 +41,7 @@ if [ "$INSTALL_TB" == "true" ]; then -Dspring.jpa.hibernate.ddl-auto=none \ -Dinstall.upgrade=false \ -Dlogging.config=/usr/share/thingsboard/bin/install/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher elif [ "$UPGRADE_TB" == "true" ]; then @@ -59,7 +59,7 @@ elif [ "$UPGRADE_TB" == "true" ]; then -Dinstall.upgrade=true \ -Dinstall.upgrade.from_version=${fromVersion} \ -Dlogging.config=/usr/share/thingsboard/bin/install/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher else @@ -68,6 +68,6 @@ else exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.ThingsboardServerApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher fi diff --git a/msa/tb/docker/install-tb.sh b/msa/tb/docker/install-tb.sh index 75970a79ef..9567908316 100644 --- a/msa/tb/docker/install-tb.sh +++ b/msa/tb/docker/install-tb.sh @@ -53,6 +53,6 @@ java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.ThingsboardI -Dspring.jpa.hibernate.ddl-auto=none \ -Dinstall.upgrade=false \ -Dlogging.config=/usr/share/thingsboard/bin/install/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher echo "${pkg.upgradeVersion}" > ${upgradeversion} diff --git a/msa/tb/docker/start-tb.sh b/msa/tb/docker/start-tb.sh index 49f2e3e5ae..21a62f5b6d 100755 --- a/msa/tb/docker/start-tb.sh +++ b/msa/tb/docker/start-tb.sh @@ -34,7 +34,7 @@ if [ -f ${firstlaunch} ]; then java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.ThingsboardServerApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=${CONF_FOLDER}/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher else echo "ERROR: ThingsBoard is not installed" fi diff --git a/msa/tb/docker/upgrade-tb.sh b/msa/tb/docker/upgrade-tb.sh index dbfdf68a32..545bf4b8d6 100644 --- a/msa/tb/docker/upgrade-tb.sh +++ b/msa/tb/docker/upgrade-tb.sh @@ -40,7 +40,7 @@ java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.ThingsboardI -Dinstall.upgrade=true \ -Dinstall.upgrade.from_version=${fromVersion} \ -Dlogging.config=/usr/share/thingsboard/bin/install/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher echo "${pkg.upgradeVersion}" > ${upgradeversion} diff --git a/msa/transport/coap/docker/start-tb-coap-transport.sh b/msa/transport/coap/docker/start-tb-coap-transport.sh index f073494bb2..75b56c205d 100755 --- a/msa/transport/coap/docker/start-tb-coap-transport.sh +++ b/msa/transport/coap/docker/start-tb-coap-transport.sh @@ -30,4 +30,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.coap.ThingsboardCoapTransportApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/msa/transport/http/docker/start-tb-http-transport.sh b/msa/transport/http/docker/start-tb-http-transport.sh index 3737523b39..eacb65e2ef 100755 --- a/msa/transport/http/docker/start-tb-http-transport.sh +++ b/msa/transport/http/docker/start-tb-http-transport.sh @@ -30,4 +30,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.http.ThingsboardHttpTransportApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/msa/transport/lwm2m/docker/start-tb-lwm2m-transport.sh b/msa/transport/lwm2m/docker/start-tb-lwm2m-transport.sh index e1e95fb78f..d88ad849f2 100755 --- a/msa/transport/lwm2m/docker/start-tb-lwm2m-transport.sh +++ b/msa/transport/lwm2m/docker/start-tb-lwm2m-transport.sh @@ -30,4 +30,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.lwm2m.ThingsboardLwm2mTransportApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/msa/transport/mqtt/docker/start-tb-mqtt-transport.sh b/msa/transport/mqtt/docker/start-tb-mqtt-transport.sh index ea0f21ea24..7350965861 100755 --- a/msa/transport/mqtt/docker/start-tb-mqtt-transport.sh +++ b/msa/transport/mqtt/docker/start-tb-mqtt-transport.sh @@ -30,4 +30,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.mqtt.ThingsboardMqttTransportApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/msa/transport/snmp/docker/start-tb-snmp-transport.sh b/msa/transport/snmp/docker/start-tb-snmp-transport.sh index 1d39301d38..20d4809958 100644 --- a/msa/transport/snmp/docker/start-tb-snmp-transport.sh +++ b/msa/transport/snmp/docker/start-tb-snmp-transport.sh @@ -30,4 +30,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.snmp.ThingsboardSnmpTransportApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/msa/vc-executor-docker/docker/start-tb-vc-executor.sh b/msa/vc-executor-docker/docker/start-tb-vc-executor.sh index ec7bf39427..09aef7d97f 100755 --- a/msa/vc-executor-docker/docker/start-tb-vc-executor.sh +++ b/msa/vc-executor-docker/docker/start-tb-vc-executor.sh @@ -30,4 +30,4 @@ cd ${pkg.installFolder}/bin exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.vc.ThingsboardVersionControlExecutorApplication \ -Dspring.jpa.hibernate.ddl-auto=none \ -Dlogging.config=/config/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher diff --git a/packaging/java/scripts/install/install.sh b/packaging/java/scripts/install/install.sh index 159d612976..450064f6f2 100755 --- a/packaging/java/scripts/install/install.sh +++ b/packaging/java/scripts/install/install.sh @@ -52,7 +52,7 @@ su -s /bin/sh -c "java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.s -Dspring.jpa.hibernate.ddl-auto=none \ -Dinstall.upgrade=false \ -Dlogging.config=${pkg.installFolder}/bin/install/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher" "$run_user" + org.springframework.boot.loader.launch.PropertiesLauncher" "$run_user" if [ $? -ne 0 ]; then echo "ThingsBoard installation failed!" diff --git a/packaging/java/scripts/install/install_dev_db.sh b/packaging/java/scripts/install/install_dev_db.sh index ca9affe596..78100554a9 100644 --- a/packaging/java/scripts/install/install_dev_db.sh +++ b/packaging/java/scripts/install/install_dev_db.sh @@ -36,7 +36,7 @@ sudo -u "$run_user" -s /bin/sh -c "java -cp ${jarfile} $JAVA_OPTS -Dloader.main= -Dspring.jpa.hibernate.ddl-auto=none \ -Dinstall.upgrade=false \ -Dlogging.config=logback.xml \ - org.springframework.boot.loader.PropertiesLauncher" + org.springframework.boot.loader.launch.PropertiesLauncher" if [ $? -ne 0 ]; then echo "ThingsBoard DB installation failed!" diff --git a/packaging/java/scripts/install/upgrade.sh b/packaging/java/scripts/install/upgrade.sh index 9011db73d2..2b87b26aa6 100755 --- a/packaging/java/scripts/install/upgrade.sh +++ b/packaging/java/scripts/install/upgrade.sh @@ -51,7 +51,7 @@ su -s /bin/sh -c "java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.s -Dinstall.upgrade=true \ -Dinstall.upgrade.from_version=${fromVersion} \ -Dlogging.config=${pkg.installFolder}/bin/install/logback.xml \ - org.springframework.boot.loader.PropertiesLauncher" "$run_user" + org.springframework.boot.loader.launch.PropertiesLauncher" "$run_user" if [ $? -ne 0 ]; then echo "ThingsBoard upgrade failed!" diff --git a/packaging/java/scripts/install/upgrade_dev_db.sh b/packaging/java/scripts/install/upgrade_dev_db.sh index 43cd463706..d0c42eaaa6 100755 --- a/packaging/java/scripts/install/upgrade_dev_db.sh +++ b/packaging/java/scripts/install/upgrade_dev_db.sh @@ -57,7 +57,7 @@ sudo -u "$run_user" -s /bin/sh -c "java -cp ${jarfile} $JAVA_OPTS -Dloader.main= -Dinstall.upgrade=true \ -Dinstall.upgrade.from_version=${fromVersion} \ -Dlogging.config=logback.xml \ - org.springframework.boot.loader.PropertiesLauncher" + org.springframework.boot.loader.launch.PropertiesLauncher" if [ $? -ne 0 ]; then echo "ThingsBoard DB installation failed!" diff --git a/packaging/java/scripts/windows/install.bat b/packaging/java/scripts/windows/install.bat index b0f6c9b203..075755886e 100644 --- a/packaging/java/scripts/windows/install.bat +++ b/packaging/java/scripts/windows/install.bat @@ -34,7 +34,7 @@ java -cp "%jarfile%" -Dloader.main=org.thingsboard.server.ThingsboardInstallAppl -Dspring.jpa.hibernate.ddl-auto=none^ -Dinstall.upgrade=false^ -Dlogging.config="%BASE%\install\logback.xml"^ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher if errorlevel 1 ( @echo ThingsBoard installation failed! diff --git a/packaging/java/scripts/windows/install_dev_db.bat b/packaging/java/scripts/windows/install_dev_db.bat index 6abc80fef1..522d0bfc93 100644 --- a/packaging/java/scripts/windows/install_dev_db.bat +++ b/packaging/java/scripts/windows/install_dev_db.bat @@ -19,7 +19,7 @@ java -cp %jarfile% -Dloader.main=org.thingsboard.server.ThingsboardInstallApplic -Dspring.jpa.hibernate.ddl-auto=none^ -Dinstall.upgrade=false^ -Dlogging.config=%BASE%\windows\install\logback.xml^ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher if errorlevel 1 ( @echo ThingsBoard DB installation failed! diff --git a/packaging/java/scripts/windows/upgrade.bat b/packaging/java/scripts/windows/upgrade.bat index 704d4c170d..b86121b8f1 100644 --- a/packaging/java/scripts/windows/upgrade.bat +++ b/packaging/java/scripts/windows/upgrade.bat @@ -34,7 +34,7 @@ java -cp "%jarfile%" -Dloader.main=org.thingsboard.server.ThingsboardInstallAppl -Dinstall.upgrade=true^ -Dinstall.upgrade.from_version=%fromVersion%^ -Dlogging.config="%BASE%\install\logback.xml"^ - org.springframework.boot.loader.PropertiesLauncher + org.springframework.boot.loader.launch.PropertiesLauncher if errorlevel 1 ( @echo ThingsBoard upgrade failed! diff --git a/pom.xml b/pom.xml index 332a88b758..c13c25566b 100755 --- a/pom.xml +++ b/pom.xml @@ -38,129 +38,133 @@ ${project.name} /var/log/${pkg.name} /usr/share/${pkg.name} - 2.1.1 - 4.0.0 + 3.0.0 + 4.0.2 2.4.0-b180830.0359 - 4.0.2 - 3.1.0 - 3.1.0 - 6.0.9 - 6.1.0 - 6.1.0 - 3.1.0 - 4.3.2 - 0.9.1 - 2.0.7 - 2.19.0 - 1.4.14 - 0.10 - 4.15.0 - 4.0.5 - 3.11.14 - 31.1-jre - 2.6.1 - 3.12.0 - 1.15 - 2.11.0 - 1.2 - 1.4 - 4.5.13 - 4.4.14 - 2.8.1 - 2.15.3 - 2.15.3 - 1.3.4 - 4.2.1 - 2.2.6 + 4.0.5 + 3.2.4 + 3.2.5 + 3.2.5 + 6.1.6 + 6.2.4 + 6.2.4 + 5.1.2 + 0.9.1 + 2.0.13 + 2.23.1 + 1.5.5 + 0.10 + 4.17.0 + 4.2.25 + 3.11.17 + 33.1.0-jre + 3.1.8 + 3.14.0 + 1.16.1 + 2.16.1 + 1.3.1 + 1.10.0 + 5.3.1 + 5.2.4 + 4.5.14 + 4.4.16 + 2.12.7 + 2.17.0 + 2.17.0 + 1.7.0 + 4.4.0 + 2.2.14 3.11.0 2.0.0-M14 - 2.9.0 - 2.3.30 + 2.10.1 + 2.3.32 2.0.1 - 5.5.0 + 5.6.0 3.9.2 - 3.21.9 - 1.42.1 + 3.25.3 + 1.63.0 1.2.0 - 1.18.26 - 1.2.4 + 1.18.32 + 1.2.5 1.2.5 - 4.1.93.Final - 2.0.61.Final - 1.1.7 - 1.7.0 - 4.8.0 - 3.0.0-M9 - 3.0.2 + 4.1.109.Final + 2.0.65.Final + 1.1.18 + 1.7.1 + 5.21.0 + 3.2.5 + 3.4.0 2.4.0TB - 2.2.20 - 0.7 - 1.18.2 - 1.69 + 2.2.21 + 0.8 + 1.19.0 + 1.78 2.0.1 42.7.3 org/thingsboard/server/gen/**/*, org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/* - 5.0.2 + 8.13.2 0.4.2 15.4 - 3.2.0 - 4.1.1 - 2.7.7 + 3.7.0 + 8.10.1 + 3.5.3 2.2 - 1.11.747 - 1.105.0 - 2.1.0 + 1.12.701 + 1.128.1 + 2.37.1 3.6.7 - 1.5.0 - 1.5.4 + 1.6.4 + 1.6.1 1.9.4 - 3.2.2 - 1.11.0 + 4.4 + 1.12.5 1.0.4TB - 3.4.0 - 9.6.1 - 8.0.0.Final - 3.5.2 + 3.7.1 + 10.1.3 + 8.0.1.Final + 3.7.4 4.0.2 3.0.2 - 1.7.3 - 2.8.5 + 1.7.5 + 3.8.0 + 2.9.0 - 4.2.0 - 2.7.2 - 1.5.2 - 5.9.3 - 2.6.0 + 4.2.1 + 2.7.3 + 1.5.6 + 5.10.2 5.15.0 1.3.0 1.2.7 5.0.0 - 7.6.1 - 3.23.1 - 5.2.0 - 1.3 - 1.18.3 + 7.10.1 + 3.25.3 + 5.4.0 + 2.2 + 1.19.7 1.12 - 3.0.0 - 6.1.0.202203080745-r + 4.19.1 + 5.8.0 + 2.27.0 + 2.12.0 + + 3.0.2 + 6.9.0.202403050737-r 0.4.8 1.0.0 - 4.6.0 - 5.2.0 - 2.21.0 - 2.12.0 - 1.12.1 - 6.4.2 - 1.34.1 + + 1.39.0 + 6.6.0 + 1.35.0 1.17 2.19.0 - 8.0.1 + 9.2.0 @@ -1310,6 +1314,11 @@ netty-codec ${netty.version} + + io.netty + netty-codec-dns + ${netty.version} + io.netty netty-codec-http @@ -1350,6 +1359,27 @@ netty-resolver ${netty.version} + + io.netty + netty-resolver-dns + ${netty.version} + + + io.netty + netty-resolver-dns-classes-macos + ${netty.version} + + + io.netty + netty-resolver-dns-native-macos + ${netty.version} + + + io.netty + netty-resolver-dns-native-macos + ${netty.version} + osx-x86_64 + io.netty netty-transport @@ -1432,6 +1462,16 @@ commons-csv ${commons-csv.version} + + org.apache.httpcomponents.client5 + httpclient5 + ${apache-httpclient5.version} + + + org.apache.httpcomponents.core5 + httpcore5 + ${apache-httpcore5.version} + org.apache.httpcomponents httpclient @@ -1467,6 +1507,11 @@ jackson-dataformat-cbor ${jackson.version} + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + com.fasterxml.jackson.datatype jackson-datatype-jdk8 @@ -1498,7 +1543,7 @@ ${auth0-jwt.version} - com.github.fge + com.github.java-json-tools json-schema-validator ${json-schema-validator.version} @@ -1627,6 +1672,56 @@ grpc-protobuf ${grpc.version} + + io.grpc + grpc-protobuf-lite + ${grpc.version} + + + io.grpc + grpc-rls + ${grpc.version} + + + io.grpc + grpc-util + ${grpc.version} + + + io.grpc + grpc-googleapis + ${grpc.version} + + + io.grpc + grpc-xds + ${grpc.version} + + + io.grpc + grpc-services + ${grpc.version} + + + io.grpc + grpc-context + ${grpc.version} + + + io.grpc + grpc-inprocess + ${grpc.version} + + + io.grpc + grpc-core + ${grpc.version} + + + io.grpc + grpc-grpclb + ${grpc.version} + io.grpc grpc-stub @@ -1736,7 +1831,7 @@ org.hamcrest - hamcrest-all + hamcrest ${hamcrest.version} test @@ -1785,12 +1880,22 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk18on + ${bouncycastle.version} + + + org.bouncycastle + bcpkix-jdk18on ${bouncycastle.version} org.bouncycastle - bcpkix-jdk15on + bcutil-jdk18on + ${bouncycastle.version} + + + org.bouncycastle + bcprov-ext-jdk18on ${bouncycastle.version} @@ -1836,7 +1941,7 @@ org.elasticsearch.client - rest + elasticsearch-rest-client ${elasticsearch.version} @@ -1845,7 +1950,7 @@ ${delight-nashorn-sandbox.version} - com.github.vladimir-bukhtoyarov + com.bucket4j bucket4j-core ${bucket4j.version} @@ -1910,8 +2015,8 @@ ${commons-beanutils.version} - commons-collections - commons-collections + org.apache.commons + commons-collections4 ${commons-collections.version} @@ -1975,7 +2080,7 @@ io.hypersistence - hypersistence-utils-hibernate-62 + hypersistence-utils-hibernate-63 ${hypersistence-utils.version} diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 895da628b9..224aea3137 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -114,7 +114,7 @@ org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on org.locationtech.spatial4j diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java index 2992bf27d5..c7ef41d909 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java @@ -21,7 +21,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java index 79c18f9a8c..17f19e3b85 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.util; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.data.DeviceRelationsQuery; import org.thingsboard.server.common.data.device.DeviceSearchQuery; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java index eadef5a013..82026f97dd 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.util; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.data.RelationsQuery; import org.thingsboard.server.common.data.id.EntityId; diff --git a/ui-ngx/src/app/app.component.ts b/ui-ngx/src/app/app.component.ts index cf53929e54..9ac5bc79a1 100644 --- a/ui-ngx/src/app/app.component.ts +++ b/ui-ngx/src/app/app.component.ts @@ -21,17 +21,15 @@ import { Component, OnInit } from '@angular/core'; import { environment as env } from '@env/environment'; import { TranslateService } from '@ngx-translate/core'; -import { select, Store } from '@ngrx/store'; +import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { LocalStorageService } from '@core/local-storage/local-storage.service'; import { DomSanitizer } from '@angular/platform-browser'; import { MatIconRegistry } from '@angular/material/icon'; -import { combineLatest } from 'rxjs'; -import { getCurrentAuthState, selectIsAuthenticated, selectIsUserLoaded } from '@core/auth/auth.selectors'; -import { distinctUntilChanged, filter, map, skip, tap } from 'rxjs/operators'; +import { getCurrentAuthState, selectUserReady } from '@core/auth/auth.selectors'; +import { filter, skip, tap } from 'rxjs/operators'; import { AuthService } from '@core/auth/auth.service'; import { svgIcons, svgIconsUrl } from '@shared/models/icon.models'; -import { isEqual } from '@core/utils'; import { ActionSettingsChangeLanguage } from '@core/settings/settings.actions'; import { SETTINGS_KEY } from '@core/settings/settings.effects'; @@ -90,13 +88,8 @@ export class AppComponent implements OnInit { } setupAuth() { - combineLatest([ - this.store.pipe(select(selectIsAuthenticated)), - this.store.pipe(select(selectIsUserLoaded))] - ).pipe( - map(results => ({isAuthenticated: results[0], isUserLoaded: results[1]})), + this.store.select(selectUserReady).pipe( filter((data) => data.isUserLoaded), - distinctUntilChanged((a, b) => isEqual(a, b)), tap((data) => { let userLang = getCurrentAuthState(this.store).userDetails?.additionalInfo?.lang ?? null; if (!userLang && !data.isAuthenticated) { diff --git a/ui-ngx/src/app/core/auth/auth.selectors.ts b/ui-ngx/src/app/core/auth/auth.selectors.ts index fc8fdc18b0..0cb13c9865 100644 --- a/ui-ngx/src/app/core/auth/auth.selectors.ts +++ b/ui-ngx/src/app/core/auth/auth.selectors.ts @@ -42,6 +42,12 @@ export const selectIsUserLoaded = createSelector( (state: AuthState) => state.isUserLoaded ); +export const selectUserReady = createSelector( + selectIsAuthenticated, + selectIsUserLoaded, + (isAuthenticated, isUserLoaded) => ({isAuthenticated, isUserLoaded}) +); + export const selectAuthUser = createSelector( selectAuthState, (state: AuthState) => state.authUser diff --git a/ui-ngx/src/app/core/auth/auth.service.ts b/ui-ngx/src/app/core/auth/auth.service.ts index ea3dfb4143..48018e9317 100644 --- a/ui-ngx/src/app/core/auth/auth.service.ts +++ b/ui-ngx/src/app/core/auth/auth.service.ts @@ -546,14 +546,14 @@ export class AuthService { this.notifyUserLoaded(false); this.loadUser(false).subscribe( (authPayload) => { - this.notifyUserLoaded(true); this.notifyAuthenticated(authPayload); + this.notifyUserLoaded(true); authenticatedSubject.next(true); authenticatedSubject.complete(); }, () => { - this.notifyUserLoaded(true); this.notifyUnauthenticated(); + this.notifyUserLoaded(true); authenticatedSubject.next(false); authenticatedSubject.complete(); } diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts index 97b353555a..baee27ff73 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts @@ -165,8 +165,7 @@ export class SentTableConfigResolver implements Resolve countError += Object.keys(stats.errors[method]).length); + const countError = stats.totalErrors; if (countError === 0) { return ''; } diff --git a/ui-ngx/src/app/shared/components/json-content.component.ts b/ui-ngx/src/app/shared/components/json-content.component.ts index dfcfcfbf3f..d79feacfbc 100644 --- a/ui-ngx/src/app/shared/components/json-content.component.ts +++ b/ui-ngx/src/app/shared/components/json-content.component.ts @@ -18,13 +18,11 @@ import { ChangeDetectorRef, Component, ElementRef, - EventEmitter, forwardRef, Input, OnChanges, OnDestroy, OnInit, - Output, SimpleChanges, ViewChild, ViewEncapsulation @@ -104,9 +102,6 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid @coerceBoolean() required: boolean; - @Output() - blur: EventEmitter = new EventEmitter(); - fullscreen = false; contentBody: string; @@ -116,7 +111,6 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid errorShowed = false; private propagateChange = null; - private onTouched = () => {}; constructor(public elementRef: ElementRef, protected store: Store, @@ -156,14 +150,12 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid this.updateView(); } }); - this.jsonEditor.on('blur', () => { - if (this.validateContent) { + if (this.validateContent) { + this.jsonEditor.on('blur', () => { this.contentValid = this.doValidate(true); this.cd.markForCheck(); - } - this.onTouched(); - this.blur.next(); - }); + }); + } if (this.tbPlaceholder && this.tbPlaceholder.length) { this.createPlaceholder(); @@ -251,7 +243,6 @@ export class JsonContentComponent implements OnInit, ControlValueAccessor, Valid } registerOnTouched(fn: any): void { - this.onTouched = fn; } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/shared/models/notification.models.ts b/ui-ngx/src/app/shared/models/notification.models.ts index 2cc7d8547b..b8097d18cb 100644 --- a/ui-ngx/src/app/shared/models/notification.models.ts +++ b/ui-ngx/src/app/shared/models/notification.models.ts @@ -81,7 +81,7 @@ export interface NotificationRequestPreview { export interface NotificationRequestStats { sent: Map; errors: { [key in NotificationDeliveryMethod]: {[errorKey in string]: string}}; - processedRecipients: Map>; + totalErrors: number; } export interface NotificationRequestConfig {