diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml
index ee9c1eae75..75048197d3 100644
--- a/common/cluster-api/pom.xml
+++ b/common/cluster-api/pom.xml
@@ -60,10 +60,6 @@
jakarta.annotation
jakarta.annotation-api
-
- com.github.java-json-tools
- json-schema-validator
-
org.slf4j
slf4j-api
diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml
index d7142e723d..d3027356c3 100644
--- a/common/dao-api/pom.xml
+++ b/common/dao-api/pom.xml
@@ -56,10 +56,6 @@
jakarta.annotation
jakarta.annotation-api
-
- com.github.java-json-tools
- json-schema-validator
-
org.slf4j
slf4j-api
diff --git a/dao/pom.xml b/dao/pom.xml
index f203343c89..9618c38386 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -59,6 +59,10 @@
org.thingsboard.common
util
+
+ com.networknt
+ json-schema-validator
+
org.slf4j
slf4j-api
diff --git a/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java b/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java
index 5acf1b0f97..2c5d6fb3c5 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/component/BaseComponentDescriptorService.java
@@ -16,10 +16,10 @@
package org.thingsboard.server.dao.component;
import com.fasterxml.jackson.databind.JsonNode;
-import com.github.fge.jsonschema.core.exceptions.ProcessingException;
-import com.github.fge.jsonschema.core.report.ProcessingReport;
-import com.github.fge.jsonschema.main.JsonSchemaFactory;
-import com.github.fge.jsonschema.main.JsonValidator;
+import com.networknt.schema.JsonSchema;
+import com.networknt.schema.JsonSchemaFactory;
+import com.networknt.schema.SpecVersion;
+import com.networknt.schema.ValidationMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -36,6 +36,7 @@ import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.Validator;
import java.util.Optional;
+import java.util.Set;
/**
* @author Andrew Shvayka
@@ -89,15 +90,18 @@ public class BaseComponentDescriptorService implements ComponentDescriptorServic
@Override
public boolean validate(TenantId tenantId, ComponentDescriptor component, JsonNode configuration) {
- JsonValidator validator = JsonSchemaFactory.byDefault().getValidator();
try {
if (!component.getConfigurationDescriptor().has("schema")) {
throw new DataValidationException("Configuration descriptor doesn't contain schema property!");
}
JsonNode configurationSchema = component.getConfigurationDescriptor().get("schema");
- ProcessingReport report = validator.validate(configurationSchema, configuration);
- return report.isSuccess();
- } catch (ProcessingException e) {
+
+ JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4);
+ JsonSchema schema = factory.getSchema(configurationSchema);
+
+ Set validationMessages = schema.validate(configuration);
+ return validationMessages.isEmpty();
+ } catch (Exception e) {
throw new IncorrectParameterException(e.getMessage(), e);
}
}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/component/BaseComponentDescriptorServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/component/BaseComponentDescriptorServiceTest.java
new file mode 100644
index 0000000000..d76c11f708
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/component/BaseComponentDescriptorServiceTest.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright © 2016-2025 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.dao.component;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.plugin.ComponentClusteringMode;
+import org.thingsboard.server.common.data.plugin.ComponentDescriptor;
+import org.thingsboard.server.common.data.plugin.ComponentScope;
+import org.thingsboard.server.common.data.plugin.ComponentType;
+import org.thingsboard.server.dao.exception.IncorrectParameterException;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class BaseComponentDescriptorServiceTest {
+
+ private BaseComponentDescriptorService service;
+ private ComponentDescriptor componentDescriptor;
+ private TenantId tenantId;
+
+ @BeforeEach
+ void setUp() {
+ service = Mockito.spy(BaseComponentDescriptorService.class);
+ tenantId = TenantId.SYS_TENANT_ID;
+
+ // Create a simple component descriptor
+ componentDescriptor = new ComponentDescriptor();
+ componentDescriptor.setType(ComponentType.ACTION);
+ componentDescriptor.setScope(ComponentScope.TENANT);
+ componentDescriptor.setClusteringMode(ComponentClusteringMode.ENABLED);
+ componentDescriptor.setName("Test Component");
+ componentDescriptor.setClazz("org.thingsboard.test.TestComponent");
+
+ // Create configuration descriptor with schema from JSON string
+ String configDescriptorJson = """
+ {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "testField": {
+ "type": "string"
+ }
+ },
+ "required": ["testField"]
+ }
+ }""";
+
+ componentDescriptor.setConfigurationDescriptor(JacksonUtil.toJsonNode(configDescriptorJson));
+ }
+
+ @Test
+ void testValidate() {
+ // Create valid configuration from JSON string
+ String validConfigJson = "{\"testField\": \"test value\"}";
+ JsonNode validConfig = JacksonUtil.toJsonNode(validConfigJson);
+
+ // Create invalid configuration (missing required field) from JSON string
+ String invalidConfigJson = "{}";
+ JsonNode invalidConfig = JacksonUtil.toJsonNode(invalidConfigJson);
+
+ // Test valid configuration
+ boolean validResult = service.validate(tenantId, componentDescriptor, validConfig);
+ assertTrue(validResult, "Valid configuration should pass validation");
+
+ // Test invalid configuration
+ boolean invalidResult = service.validate(tenantId, componentDescriptor, invalidConfig);
+ assertFalse(invalidResult, "Invalid configuration should fail validation");
+
+ // Test with component descriptor without schema
+ ComponentDescriptor noSchemaDescriptor = new ComponentDescriptor(componentDescriptor);
+ noSchemaDescriptor.setConfigurationDescriptor(JacksonUtil.toJsonNode("{}"));
+
+ // Should throw exception when schema is missing
+ assertThrows(IncorrectParameterException.class, () -> {
+ service.validate(tenantId, noSchemaDescriptor, validConfig);
+ }, "Should throw exception when schema is missing");
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index f95e9df9b1..608a46584a 100755
--- a/pom.xml
+++ b/pom.xml
@@ -42,13 +42,14 @@
4.0.2
2.4.0-b180830.0359
4.0.5
- 10.1.39
+ 10.1.40
+ 2.5.2
3.2.12
3.2.12
3.2.12
6.1.15
6.2.11
- 6.2.8
+ 6.3.8
5.1.5
0.12.5
2.0.13
@@ -57,7 +58,7 @@
0.10
4.17.0
4.2.25
- 3.11.17
+ 5.0.4
33.1.0-jre
3.1.8
3.14.0
@@ -74,7 +75,7 @@
2.17.2
1.7.0
4.4.0
- 2.2.14
+ 1.5.6
0.6.12
3.12.1
2.0.0-M15
@@ -102,7 +103,7 @@
1.19.0
1.78.1
2.0.1
- 42.7.3
+ 42.7.5
org/thingsboard/server/gen/**/*,
org/thingsboard/server/extensions/core/plugin/telemetry/gen/**/*
@@ -112,7 +113,7 @@
- 3.7.1
+ 3.7.2
8.10.1
3.5.3
2.2
@@ -1163,6 +1164,13 @@
tomcat-embed-websocket
${tomcat.version}
+
+
+ net.minidev
+ json-smart
+ ${net.minidev.json-smart}
+
+
org.springframework.boot
spring-boot-starter
@@ -1183,6 +1191,18 @@
spring-security-oauth2-jose
${spring-security.version}
+
+
+ org.springframework.security
+ spring-security-config
+ ${spring-security.version}
+
+
+ org.springframework.security
+ spring-security-web
+ ${spring-security.version}
+
+
org.springframework
spring-core
@@ -1600,15 +1620,9 @@
${auth0-jwt.version}
- com.github.java-json-tools
+ com.networknt
json-schema-validator
${json-schema-validator.version}
-
-
- com.sun.mail
- mailapi
-
-
org.eclipse.leshan
@@ -1827,11 +1841,6 @@
cassandra-all
${cassandra-all.version}
-
- org.apache.cassandra
- cassandra-thrift
- ${cassandra-all.version}
-
org.junit.vintage
junit-vintage-engine
@@ -2224,7 +2233,7 @@
org.mock-server
- mockserver-netty
+ mockserver-netty-no-dependencies
${mock-server.version}
test
@@ -2236,7 +2245,7 @@
org.mock-server
- mockserver-client-java
+ mockserver-client-java-no-dependencies
${mock-server.version}
test
diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml
index 008c422dbf..b975f7c624 100644
--- a/rule-engine/rule-engine-components/pom.xml
+++ b/rule-engine/rule-engine-components/pom.xml
@@ -141,12 +141,12 @@
org.mock-server
- mockserver-netty
+ mockserver-netty-no-dependencies
test
org.mock-server
- mockserver-client-java
+ mockserver-client-java-no-dependencies
test
diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java
index bf650af8bb..2438e59106 100644
--- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java
+++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mqtt/TbMqttNodeTest.java
@@ -181,7 +181,8 @@ public class TbMqttNodeTest extends AbstractRuleNodeUpgradeTest {
SslContext actualSslContext = mqttClientConfig.getValue().getSslContext();
assertThat(actualSslContext)
.usingRecursiveComparison()
- .ignoringFields("ctx", "ctxLock", "sessionContext.context.ctx", "sessionContext.context.ctxLock")
+ .ignoringFields("ctx", "ctxLock", "sessionContext.context.ctx", "sessionContext.context.ctxLock",
+ "sslContext")
.isEqualTo(SslContextBuilder.forClient().build());
}
diff --git a/tools/pom.xml b/tools/pom.xml
index 0286c135e4..7e2c44ddd6 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -55,10 +55,6 @@
org.apache.cassandra
cassandra-all
-
- org.apache.cassandra
- cassandra-thrift
-
commons-io
commons-io
diff --git a/tools/src/main/java/org/thingsboard/client/tools/migrator/WriterBuilder.java b/tools/src/main/java/org/thingsboard/client/tools/migrator/WriterBuilder.java
index b7f8524031..80fdad3c1c 100644
--- a/tools/src/main/java/org/thingsboard/client/tools/migrator/WriterBuilder.java
+++ b/tools/src/main/java/org/thingsboard/client/tools/migrator/WriterBuilder.java
@@ -59,7 +59,7 @@ public class WriterBuilder {
public static CQLSSTableWriter getTsWriter(File dir) {
return CQLSSTableWriter.builder()
- .inDirectory(dir)
+ .inDirectory(dir.getAbsolutePath())
.forTable(tsSchema)
.using("INSERT INTO thingsboard.ts_kv_cf (entity_type, entity_id, key, partition, ts, bool_v, str_v, long_v, dbl_v, json_v) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
@@ -68,7 +68,7 @@ public class WriterBuilder {
public static CQLSSTableWriter getLatestWriter(File dir) {
return CQLSSTableWriter.builder()
- .inDirectory(dir)
+ .inDirectory(dir.getAbsolutePath())
.forTable(latestSchema)
.using("INSERT INTO thingsboard.ts_kv_latest_cf (entity_type, entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
@@ -77,7 +77,7 @@ public class WriterBuilder {
public static CQLSSTableWriter getPartitionWriter(File dir) {
return CQLSSTableWriter.builder()
- .inDirectory(dir)
+ .inDirectory(dir.getAbsolutePath())
.forTable(partitionSchema)
.using("INSERT INTO thingsboard.ts_kv_partitions_cf (entity_type, entity_id, key, partition) " +
"VALUES (?, ?, ?, ?)")
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html
index 2d3f230643..8849d60c77 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html
+++ b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html
@@ -116,11 +116,12 @@
rule-node-config.polygon-definition
-
help
+
{{ 'rule-node-config.polygon-definition-required' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html
index c9685f2c3f..aee7b9cd83 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html
+++ b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html
@@ -22,6 +22,7 @@
help
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html
index 9a6d06255d..f41613c6fb 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html
+++ b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html
@@ -76,9 +76,10 @@
requiredText="{{ 'rule-node-config.default-ttl-required' | translate }}"
minErrorText="{{ 'rule-node-config.min-default-ttl-message' | translate }}"
formControlName="defaultTTL">
-
help