Browse Source

Merge remote-tracking branch 'upstream/master' into edge-improve-stability-test

pull/10624/head
Andrii Landiak 2 years ago
parent
commit
01bfcff415
  1. 25
      application/src/main/java/org/apache/kafka/common/network/NetworkReceive.java
  2. 2
      application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java
  3. 2
      application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java
  4. 2
      application/src/main/java/org/thingsboard/server/service/device/DeviceBulkImportService.java
  5. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java
  6. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java
  7. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmTriggerProcessor.java
  8. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/DeviceActivityTriggerProcessor.java
  9. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeCommunicationFailureTriggerProcessor.java
  10. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EdgeConnectionTriggerProcessor.java
  11. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntitiesLimitTriggerProcessor.java
  12. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java
  13. 2
      application/src/main/java/org/thingsboard/server/service/sync/ie/exporting/impl/DashboardExportService.java
  14. 2
      application/src/main/java/org/thingsboard/server/service/sync/ie/importing/impl/NotificationTargetImportService.java
  15. 2
      application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java
  16. 6
      application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java
  17. 2
      common/cluster-api/pom.xml
  18. 2
      common/dao-api/pom.xml
  19. 2
      common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java
  20. 4
      common/message/pom.xml
  21. 2
      common/message/src/main/java/org/thingsboard/server/common/msg/EncryptionUtil.java
  22. 4
      common/message/src/main/java/org/thingsboard/server/common/msg/tools/TbRateLimits.java
  23. 30
      common/message/src/test/java/org/thingsboard/server/common/msg/EncryptionUtilTest.java
  24. 4
      common/transport/transport-api/pom.xml
  25. 8
      common/util/pom.xml
  26. 60
      common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java
  27. 16
      common/util/src/test/java/org/thingsboard/common/util/JacksonUtilTest.java
  28. 12
      dao/pom.xml
  29. 5
      dao/src/main/java/org/thingsboard/server/dao/ThingsboardPostgreSQLDialect.java
  30. 11
      dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java
  31. 2
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationTargetService.java
  32. 2
      dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java
  33. 2
      dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java
  34. 2
      dao/src/main/java/org/thingsboard/server/dao/service/validator/RuleChainDataValidator.java
  35. 40
      dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java
  36. 14
      dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java
  37. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java
  38. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
  39. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java
  40. 32
      dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDaoTest.java
  41. 2
      msa/black-box-tests/pom.xml
  42. 2
      msa/monitoring/docker/start-tb-monitoring.sh
  43. 6
      msa/tb-node/docker/start-tb-node.sh
  44. 2
      msa/tb/docker/install-tb.sh
  45. 2
      msa/tb/docker/start-tb.sh
  46. 2
      msa/tb/docker/upgrade-tb.sh
  47. 2
      msa/transport/coap/docker/start-tb-coap-transport.sh
  48. 2
      msa/transport/http/docker/start-tb-http-transport.sh
  49. 2
      msa/transport/lwm2m/docker/start-tb-lwm2m-transport.sh
  50. 2
      msa/transport/mqtt/docker/start-tb-mqtt-transport.sh
  51. 2
      msa/transport/snmp/docker/start-tb-snmp-transport.sh
  52. 2
      msa/vc-executor-docker/docker/start-tb-vc-executor.sh
  53. 2
      packaging/java/scripts/install/install.sh
  54. 2
      packaging/java/scripts/install/install_dev_db.sh
  55. 2
      packaging/java/scripts/install/upgrade.sh
  56. 2
      packaging/java/scripts/install/upgrade_dev_db.sh
  57. 2
      packaging/java/scripts/windows/install.bat
  58. 2
      packaging/java/scripts/windows/install_dev_db.bat
  59. 2
      packaging/java/scripts/windows/upgrade.bat
  60. 299
      pom.xml
  61. 2
      rule-engine/rule-engine-components/pom.xml
  62. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java
  63. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoader.java
  64. 2
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoader.java
  65. 15
      ui-ngx/src/app/app.component.ts
  66. 6
      ui-ngx/src/app/core/auth/auth.selectors.ts
  67. 4
      ui-ngx/src/app/core/auth/auth.service.ts
  68. 17
      ui-ngx/src/app/shared/components/json-content.component.ts

25
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) {

2
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;

2
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;

2
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;

2
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

2
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

2
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

2
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;

2
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;

2
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;

2
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

2
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;

2
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;

2
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;

2
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;

6
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();

2
common/cluster-api/pom.xml

@ -61,7 +61,7 @@
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>com.github.fge</groupId>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-schema-validator</artifactId>
</dependency>
<dependency>

2
common/dao-api/pom.xml

@ -57,7 +57,7 @@
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>com.github.fge</groupId>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-schema-validator</artifactId>
</dependency>
<dependency>

2
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() {

4
common/message/pom.xml

@ -42,7 +42,7 @@
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@ -61,7 +61,7 @@
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j-core</artifactId>
</dependency>
<dependency>

2
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

4
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]);

30
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");
}
}

4
common/transport/transport-api/pom.xml

@ -127,11 +127,11 @@
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>
</dependencies>

8
common/util/pom.xml

@ -38,11 +38,11 @@
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@ -104,6 +104,10 @@
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
</dependencies>
<build>

60
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> T convertValue(Object fromValue, Class<T> 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> 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> T readValue(File file, TypeReference<T> clazz) {
try {
return OBJECT_MAPPER.readValue(file, clazz);
} catch (IOException e) {
throw new IllegalArgumentException("Can't read file: " + file, e);
}
}
public static <T> T readValue(File file, Class<T> 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;

16
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]");
}
}

12
dao/pom.xml

@ -81,7 +81,7 @@
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -113,8 +113,8 @@
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
@ -190,7 +190,7 @@
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -222,7 +222,7 @@
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>rest</artifactId>
<artifactId>elasticsearch-rest-client</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.leshan</groupId>
@ -238,7 +238,7 @@
</dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-62</artifactId>
<artifactId>hypersistence-utils-hibernate-63</artifactId>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>

5
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));
}
}

11
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) {

2
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

2
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;

2
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;

2
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;

40
dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java

@ -57,7 +57,7 @@ public interface AlarmRepository extends JpaRepository<AlarmEntity, UUID> {
"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<AlarmEntity, UUID> {
"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<AlarmEntity, UUID> {
@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<AlarmEntity, UUID> {
// "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<AlarmEntity, UUID> {
// "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<AlarmEntity, UUID> {
@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<AlarmEntity, UUID> {
"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<AlarmEntity, UUID> {
"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<AlarmEntity, UUID> {
@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<AlarmEntity, UUID> {
// "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<AlarmEntity, UUID> {
// "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<AlarmEntity, UUID> {
@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<AlarmEntity, UUID> {
"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<AlarmEntity, UUID> {
"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<AlarmEntity, UUID> {
@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<AlarmEntity, UUID> {
// "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<AlarmEntity, UUID> {
// "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<AlarmEntity, UUID> {
@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<AlarmEntity, UUID> {
"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<AlarmSeverity> findAlarmSeverities(@Param("tenantId") UUID tenantId,
@Param("affectedEntityId") UUID affectedEntityId,
@Param("affectedEntityType") String affectedEntityType,
@ -322,7 +322,7 @@ public interface AlarmRepository extends JpaRepository<AlarmEntity, UUID> {
@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<UUID> findAlarmsIdsByEndTsBeforeAndTenantId(@Param("time") Long time, @Param("tenantId") UUID tenantId, Pageable pageable);

14
dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java

@ -154,7 +154,7 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> 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<AlarmEntity, Alarm> 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<AlarmEntity, Alarm> 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<AlarmEntity, Alarm> 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<AlarmEntity, Alarm> 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<AlarmEntity, Alarm> 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<AlarmEntity, Alarm> implements A
asf.hasClearFilter() && asf.getClearFilter(),
asf.hasAckFilter(),
asf.hasAckFilter() && asf.getAckFilter(),
assigneeId);
StringUtils.isNotBlank(assigneeId) ? UUID.fromString(assigneeId) : null);
}
@Override

12
dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java

@ -126,20 +126,20 @@ public interface DeviceRepository extends JpaRepository<DeviceEntity, UUID>, 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<DeviceInfoEntity> 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,

6
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java

@ -110,10 +110,10 @@ public class JpaDeviceDao extends JpaAbstractDao<DeviceEntity, Device> 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(),

2
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<UserSettings> findByTypeAndPath(TenantId tenantId, UserSettingsType type, String... path) {
log.trace("findByTypeAndPath [{}][{}][{}]", tenantId, type, path);
return DaoUtil.convertDataList(userSettingsRepository.findByTypeAndPathExisting(type.name(), path));
}

32
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);

2
msa/black-box-tests/pom.xml

@ -85,7 +85,7 @@
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>

2
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

6
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

2
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}

2
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

2
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}

2
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

2
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

2
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

2
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

2
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

2
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

2
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!"

2
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!"

2
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!"

2
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!"

2
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!

2
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!

2
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!

299
pom.xml

@ -38,129 +38,133 @@
<pkg.implementationTitle>${project.name}</pkg.implementationTitle>
<pkg.unixLogFolder>/var/log/${pkg.name}</pkg.unixLogFolder>
<pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
<jakarta-annotation.version>2.1.1</jakarta-annotation.version>
<jakarta.xml.bind-api.version>4.0.0</jakarta.xml.bind-api.version>
<jakarta-annotation.version>3.0.0</jakarta-annotation.version>
<jakarta.xml.bind-api.version>4.0.2</jakarta.xml.bind-api.version>
<javax.xml.bind-api.version>2.4.0-b180830.0359</javax.xml.bind-api.version>
<jaxb-runtime.version>4.0.2</jaxb-runtime.version>
<spring-boot.version>3.1.0</spring-boot.version>
<spring-data.version>3.1.0</spring-data.version>
<spring.version>6.0.9</spring.version>
<spring-redis.version>6.1.0</spring-redis.version>
<spring-security.version>6.1.0</spring-security.version>
<spring-data-redis.version>3.1.0</spring-data-redis.version>
<jedis.version>4.3.2</jedis.version>
<jjwt.version>0.9.1</jjwt.version>
<slf4j.version>2.0.7</slf4j.version>
<log4j.version>2.19.0</log4j.version>
<logback.version>1.4.14</logback.version>
<rat.version>0.10</rat.version>
<cassandra.version>4.15.0</cassandra.version>
<metrics.version>4.0.5</metrics.version>
<cassandra-all.version>3.11.14</cassandra-all.version>
<guava.version>31.1-jre</guava.version>
<caffeine.version>2.6.1</caffeine.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-codec.version>1.15</commons-codec.version>
<commons-io.version>2.11.0</commons-io.version>
<commons-logging.version>1.2</commons-logging.version>
<commons-csv.version>1.4</commons-csv.version>
<apache-httpclient.version>4.5.13</apache-httpclient.version>
<apache-httpcore.version>4.4.14</apache-httpcore.version>
<joda-time.version>2.8.1</joda-time.version>
<jackson.version>2.15.3</jackson.version>
<jackson-databind.version>2.15.3</jackson-databind.version>
<fasterxml-classmate.version>1.3.4</fasterxml-classmate.version>
<auth0-jwt.version>4.2.1</auth0-jwt.version>
<json-schema-validator.version>2.2.6</json-schema-validator.version>
<jaxb-runtime.version>4.0.5</jaxb-runtime.version>
<spring-boot.version>3.2.4</spring-boot.version>
<spring-data.version>3.2.5</spring-data.version>
<spring-data-redis.version>3.2.5</spring-data-redis.version>
<spring.version>6.1.6</spring.version>
<spring-redis.version>6.2.4</spring-redis.version>
<spring-security.version>6.2.4</spring-security.version>
<jedis.version>5.1.2</jedis.version>
<jjwt.version>0.9.1</jjwt.version> <!-- 0.12.5 requires JWT usage refactoring-->
<slf4j.version>2.0.13</slf4j.version>
<log4j.version>2.23.1</log4j.version>
<logback.version>1.5.5</logback.version>
<rat.version>0.10</rat.version> <!-- unused -->
<cassandra.version>4.17.0</cassandra.version>
<metrics.version>4.2.25</metrics.version>
<cassandra-all.version>3.11.17</cassandra-all.version> <!-- tools -->
<guava.version>33.1.0-jre</guava.version>
<caffeine.version>3.1.8</caffeine.version>
<commons-lang3.version>3.14.0</commons-lang3.version>
<commons-codec.version>1.16.1</commons-codec.version>
<commons-io.version>2.16.1</commons-io.version>
<commons-logging.version>1.3.1</commons-logging.version>
<commons-csv.version>1.10.0</commons-csv.version>
<apache-httpclient5.version>5.3.1</apache-httpclient5.version>
<apache-httpcore5.version>5.2.4</apache-httpcore5.version>
<apache-httpclient.version>4.5.14</apache-httpclient.version>
<apache-httpcore.version>4.4.16</apache-httpcore.version>
<joda-time.version>2.12.7</joda-time.version>
<jackson.version>2.17.0</jackson.version>
<jackson-databind.version>2.17.0</jackson-databind.version>
<fasterxml-classmate.version>1.7.0</fasterxml-classmate.version>
<auth0-jwt.version>4.4.0</auth0-jwt.version>
<json-schema-validator.version>2.2.14</json-schema-validator.version>
<californium.version>3.11.0</californium.version>
<leshan.version>2.0.0-M14</leshan.version>
<gson.version>2.9.0</gson.version>
<freemarker.version>2.3.30</freemarker.version>
<gson.version>2.10.1</gson.version>
<freemarker.version>2.3.32</freemarker.version>
<mail.version>2.0.1</mail.version>
<curator.version>5.5.0</curator.version>
<curator.version>5.6.0</curator.version>
<zookeeper.version>3.9.2</zookeeper.version>
<protobuf.version>3.21.9</protobuf.version>
<grpc.version>1.42.1</grpc.version>
<protobuf.version>3.25.3</protobuf.version> <!-- A Major v4 does not support by the pubsub yet-->
<grpc.version>1.63.0</grpc.version>
<tbel.version>1.2.0</tbel.version>
<lombok.version>1.18.26</lombok.version>
<paho.client.version>1.2.4</paho.client.version>
<lombok.version>1.18.32</lombok.version>
<paho.client.version>1.2.5</paho.client.version>
<paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version>
<netty.version>4.1.93.Final</netty.version>
<netty-tcnative.version>2.0.61.Final</netty-tcnative.version>
<reactor-netty.version>1.1.7</reactor-netty.version>
<os-maven-plugin.version>1.7.0</os-maven-plugin.version>
<rabbitmq.version>4.8.0</rabbitmq.version>
<surefire.version>3.0.0-M9</surefire.version>
<jar-plugin.version>3.0.2</jar-plugin.version>
<netty.version>4.1.109.Final</netty.version>
<netty-tcnative.version>2.0.65.Final</netty-tcnative.version>
<reactor-netty.version>1.1.18</reactor-netty.version>
<os-maven-plugin.version>1.7.1</os-maven-plugin.version>
<rabbitmq.version>5.21.0</rabbitmq.version>
<surefire.version>3.2.5</surefire.version>
<jar-plugin.version>3.4.0</jar-plugin.version>
<springdoc-swagger.version>2.4.0TB</springdoc-swagger.version>
<swagger-annotations.version>2.2.20</swagger-annotations.version>
<spatial4j.version>0.7</spatial4j.version>
<jts.version>1.18.2</jts.version>
<bouncycastle.version>1.69</bouncycastle.version>
<swagger-annotations.version>2.2.21</swagger-annotations.version>
<spatial4j.version>0.8</spatial4j.version>
<jts.version>1.19.0</jts.version>
<bouncycastle.version>1.78</bouncycastle.version>
<winsw.version>2.0.1</winsw.version>
<postgresql.driver.version>42.7.3</postgresql.driver.version>
<sonar.exclusions>org/thingsboard/server/gen/**/*,
org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/*
</sonar.exclusions>
<elasticsearch.version>5.0.2</elasticsearch.version>
<elasticsearch.version>8.13.2</elasticsearch.version>
<delight-nashorn-sandbox.version>0.4.2</delight-nashorn-sandbox.version>
<nashorn-core.version>15.4</nashorn-core.version>
<!-- IMPORTANT: If you change the version of the kafka client, make sure to synchronize our overwritten implementation of the
org.apache.kafka.common.network.NetworkReceive class in the application module. It addresses the issue https://issues.apache.org/jira/browse/KAFKA-4090.
Here is the source to track https://github.com/apache/kafka/tree/trunk/clients/src/main/java/org/apache/kafka/common/network -->
<kafka.version>3.2.0</kafka.version>
<bucket4j.version>4.1.1</bucket4j.version>
<antlr.version>2.7.7</antlr.version>
<kafka.version>3.7.0</kafka.version>
<bucket4j.version>8.10.1</bucket4j.version>
<antlr.version>3.5.3</antlr.version>
<snakeyaml.version>2.2</snakeyaml.version>
<aws.sdk.version>1.11.747</aws.sdk.version>
<pubsub.client.version>1.105.0</pubsub.client.version>
<google.common.protos.version>2.1.0</google.common.protos.version> <!-- required by io.grpc:grpc-protobuf:1.38.0-->
<aws.sdk.version>1.12.701</aws.sdk.version>
<pubsub.client.version>1.128.1</pubsub.client.version>
<google.common.protos.version>2.37.1</google.common.protos.version>
<azure-servicebus.version>3.6.7</azure-servicebus.version>
<passay.version>1.5.0</passay.version>
<ua-parser.version>1.5.4</ua-parser.version>
<passay.version>1.6.4</passay.version>
<ua-parser.version>1.6.1</ua-parser.version>
<commons-beanutils.version>1.9.4</commons-beanutils.version>
<commons-collections.version>3.2.2</commons-collections.version>
<micrometer.version>1.11.0</micrometer.version>
<commons-collections.version>4.4</commons-collections.version>
<micrometer.version>1.12.5</micrometer.version>
<protobuf-dynamic.version>1.0.4TB</protobuf-dynamic.version>
<wire-schema.version>3.4.0</wire-schema.version>
<twilio.version>9.6.1</twilio.version>
<hibernate-validator.version>8.0.0.Final</hibernate-validator.version>
<hypersistence-utils.version>3.5.2</hypersistence-utils.version>
<wire-schema.version>3.7.1</wire-schema.version>
<twilio.version>10.1.3</twilio.version>
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
<hypersistence-utils.version>3.7.4</hypersistence-utils.version> <!-- artifact name should be updated with hibernate-core version -->
<jakarta.el.version>4.0.2</jakarta.el.version>
<jakarta.validation-api.version>3.0.2</jakarta.validation-api.version>
<antisamy.version>1.7.3</antisamy.version>
<snmp4j.version>2.8.5</snmp4j.version>
<antisamy.version>1.7.5</antisamy.version>
<snmp4j.version>3.8.0</snmp4j.version>
<json-path.version>2.9.0</json-path.version>
<!-- TEST SCOPE -->
<awaitility.version>4.2.0</awaitility.version>
<dbunit.version>2.7.2</dbunit.version>
<java-websocket.version>1.5.2</java-websocket.version>
<jupiter.version>5.9.3</jupiter.version> <!-- keep the same version as spring-boot-starter-test depend on jupiter-->
<json-path.version>2.6.0</json-path.version>
<awaitility.version>4.2.1</awaitility.version>
<dbunit.version>2.7.3</dbunit.version>
<java-websocket.version>1.5.6</java-websocket.version>
<jupiter.version>5.10.2</jupiter.version> <!-- keep the same version as spring-boot-starter-test depend on jupiter-->
<mock-server.version>5.15.0</mock-server.version>
<spring-test-dbunit.version>1.3.0</spring-test-dbunit.version> <!-- 2016 -->
<takari-cpsuite.version>1.2.7</takari-cpsuite.version> <!-- 2015 -->
<jeasy.version>5.0.0</jeasy.version>
<!-- BLACKBOX TEST SCOPE -->
<testng.version>7.6.1</testng.version>
<assertj.version>3.23.1</assertj.version>
<rest-assured.version>5.2.0</rest-assured.version>
<hamcrest.version>1.3</hamcrest.version>
<testcontainers.version>1.18.3</testcontainers.version>
<testng.version>7.10.1</testng.version>
<assertj.version>3.25.3</assertj.version>
<rest-assured.version>5.4.0</rest-assured.version>
<hamcrest.version>2.2</hamcrest.version>
<testcontainers.version>1.19.7</testcontainers.version>
<zeroturnaround.version>1.12</zeroturnaround.version>
<opensmpp.version>3.0.0</opensmpp.version>
<jgit.version>6.1.0.202203080745-r</jgit.version>
<selenium.version>4.19.1</selenium.version>
<webdrivermanager.version>5.8.0</webdrivermanager.version>
<allure-testng.version>2.27.0</allure-testng.version>
<allure-maven.version>2.12.0</allure-maven.version>
<opensmpp.version>3.0.2</opensmpp.version>
<jgit.version>6.9.0.202403050737-r</jgit.version>
<exp4j.version>0.4.8</exp4j.version>
<aerogear-otp.version>1.0.0</aerogear-otp.version>
<selenium.version>4.6.0</selenium.version>
<webdrivermanager.version>5.2.0</webdrivermanager.version>
<allure-testng.version>2.21.0</allure-testng.version>
<allure-maven.version>2.12.0</allure-maven.version>
<slack-api.version>1.12.1</slack-api.version>
<oshi.version>6.4.2</oshi.version>
<google-oauth-client.version>1.34.1</google-oauth-client.version>
<slack-api.version>1.39.0</slack-api.version>
<oshi.version>6.6.0</oshi.version>
<google-oauth-client.version>1.35.0</google-oauth-client.version>
<apache-xmlgraphics.version>1.17</apache-xmlgraphics.version>
<drewnoakes-metadata-extractor.version>2.19.0</drewnoakes-metadata-extractor.version>
<firebase-admin.version>8.0.1</firebase-admin.version>
<firebase-admin.version>9.2.0</firebase-admin.version>
</properties>
<modules>
@ -1310,6 +1314,11 @@
<artifactId>netty-codec</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-dns</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
@ -1350,6 +1359,27 @@
<artifactId>netty-resolver</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-classes-macos</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-native-macos</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-native-macos</artifactId>
<version>${netty.version}</version>
<classifier>osx-x86_64</classifier>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
@ -1432,6 +1462,16 @@
<artifactId>commons-csv</artifactId>
<version>${commons-csv.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>${apache-httpclient5.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>${apache-httpcore5.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
@ -1467,6 +1507,11 @@
<artifactId>jackson-dataformat-cbor</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
@ -1498,7 +1543,7 @@
<version>${auth0-jwt.version}</version>
</dependency>
<dependency>
<groupId>com.github.fge</groupId>
<groupId>com.github.java-json-tools</groupId>
<artifactId>json-schema-validator</artifactId>
<version>${json-schema-validator.version}</version>
<exclusions>
@ -1627,6 +1672,56 @@
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf-lite</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-rls</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-util</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-googleapis</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-xds</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-context</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-inprocess</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-grpclb</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
@ -1736,7 +1831,7 @@
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
@ -1785,12 +1880,22 @@
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<artifactId>bcprov-jdk18on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<artifactId>bcutil-jdk18on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk18on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
@ -1836,7 +1941,7 @@
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>rest</artifactId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
@ -1845,7 +1950,7 @@
<version>${delight-nashorn-sandbox.version}</version>
</dependency>
<dependency>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j-core</artifactId>
<version>${bucket4j.version}</version>
</dependency>
@ -1910,8 +2015,8 @@
<version>${commons-beanutils.version}</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections.version}</version>
</dependency>
<dependency>
@ -1975,7 +2080,7 @@
</dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-62</artifactId>
<artifactId>hypersistence-utils-hibernate-63</artifactId>
<version>${hypersistence-utils.version}</version>
</dependency>
<dependency>

2
rule-engine/rule-engine-components/pom.xml

@ -114,7 +114,7 @@
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<artifactId>bcpkix-jdk18on</artifactId>
</dependency>
<dependency>
<groupId>org.locationtech.spatial4j</groupId>

2
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;

2
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;

2
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;

15
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) {

6
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

4
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();
}

17
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<void> = new EventEmitter<void>();
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<AppState>,
@ -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 {

Loading…
Cancel
Save