From 65789f2e7bcb5e4ca9d88edb9a37d1471ff60652 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 11 Jul 2024 11:03:37 +0200 Subject: [PATCH 1/5] fixed adding body condition and content-type creation --- .../rule/engine/rest/TbHttpClient.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 1db9dd2fc5..1c02d882d0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -31,6 +31,7 @@ import org.springframework.web.client.RestClientResponseException; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec; +import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.web.util.UriComponentsBuilder; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; @@ -43,11 +44,13 @@ import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import reactor.netty.http.client.HttpClient; +import reactor.netty.resources.ConnectionProvider; import reactor.netty.transport.ProxyProvider; import javax.net.ssl.SSLException; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.Base64; import java.util.List; import java.util.Map; @@ -57,6 +60,8 @@ import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; +import static io.netty.channel.ChannelOption.SO_KEEPALIVE; + @Data @Slf4j public class TbHttpClient { @@ -170,7 +175,7 @@ public class TbHttpClient { BiConsumer onFailure) { try { if (semaphore != null && !semaphore.tryAcquire(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS)) { - ctx.tellFailure(msg, new RuntimeException("Timeout during waiting for reply!")); + onFailure.accept(msg, new RuntimeException("Timeout during waiting for reply!")); return; } @@ -183,10 +188,10 @@ public class TbHttpClient { .uri(uri) .headers(headers -> prepareHeaders(headers, msg)); - if (HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method) || - HttpMethod.PATCH.equals(method) || HttpMethod.DELETE.equals(method) || + if ((HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method) || + HttpMethod.PATCH.equals(method) || HttpMethod.DELETE.equals(method)) && !config.isIgnoreRequestBody()) { - request.body(BodyInserters.fromValue(getData(msg, config.isIgnoreRequestBody(), config.isParseToPlainText()))); + request.body(BodyInserters.fromValue(getData(msg, config.isParseToPlainText()))); } request @@ -236,11 +241,9 @@ public class TbHttpClient { return uri; } - private String getData(TbMsg tbMsg, boolean ignoreBody, boolean parseToPlainText) { - if (!ignoreBody && parseToPlainText) { - return JacksonUtil.toPlainText(tbMsg.getData()); - } - return tbMsg.getData(); + private Object getData(TbMsg tbMsg, boolean parseToPlainText) { + String data = tbMsg.getData(); + return parseToPlainText ? JacksonUtil.toPlainText(data) : JacksonUtil.toJsonNode(data); } private TbMsg processResponse(TbContext ctx, TbMsg origMsg, ResponseEntity response) { @@ -283,10 +286,9 @@ public class TbHttpClient { private TbMsg processException(TbMsg origMsg, Throwable e) { TbMsgMetaData metaData = origMsg.getMetaData(); metaData.putValue(ERROR, e.getClass() + ": " + e.getMessage()); - if (e instanceof RestClientResponseException) { - RestClientResponseException restClientResponseException = (RestClientResponseException) e; + if (e instanceof WebClientResponseException restClientResponseException) { metaData.putValue(STATUS, restClientResponseException.getStatusText()); - metaData.putValue(STATUS_CODE, restClientResponseException.getRawStatusCode() + ""); + metaData.putValue(STATUS_CODE, restClientResponseException.getStatusCode().value() + ""); metaData.putValue(ERROR_BODY, restClientResponseException.getResponseBodyAsString()); } return TbMsg.transformMsgMetadata(origMsg, metaData); From 58185d4a4c42bb8bfb363e467eaeb1c82afd1325 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 11 Jul 2024 11:23:03 +0200 Subject: [PATCH 2/5] hotfix Connection reset --- .../main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 1c02d882d0..24304f33b4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -137,6 +137,7 @@ public class TbHttpClient { this.webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) + .defaultHeader(HttpHeaders.CONNECTION, "close") //In previous realization this header was present! (Added for hotfix "Connection reset") .build(); } catch (SSLException e) { throw new TbNodeException(e); From 196ec5e59de33834c1d962a71eddd9c494395d07 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 11 Jul 2024 11:33:29 +0200 Subject: [PATCH 3/5] fixed tests --- .../java/org/thingsboard/rule/engine/rest/TbHttpClient.java | 5 ----- .../thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 24304f33b4..26de3ad5e5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -27,7 +27,6 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.web.client.RestClientResponseException; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec; @@ -44,13 +43,11 @@ import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import reactor.netty.http.client.HttpClient; -import reactor.netty.resources.ConnectionProvider; import reactor.netty.transport.ProxyProvider; import javax.net.ssl.SSLException; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.Base64; import java.util.List; import java.util.Map; @@ -60,8 +57,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; -import static io.netty.channel.ChannelOption.SO_KEEPALIVE; - @Data @Slf4j public class TbHttpClient { diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 98695c1570..fad0ae66da 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -165,7 +165,7 @@ public class TbRestApiCallNodeTest { try { assertEquals(path, request.getRequestLine().getUri(), "Request path matches"); assertTrue(request.containsHeader("Content-Type"), "Content-Type included"); - assertEquals("text/plain;charset=UTF-8", + assertEquals("application/json", request.getFirstHeader("Content-Type").getValue(), "Content-Type value"); assertTrue(request.containsHeader("Content-Length"), "Content-Length included"); assertEquals("2", From 95178d12ea2f874f1ea29439428c3533239c1dad Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 11 Jul 2024 14:48:57 +0300 Subject: [PATCH 4/5] Fix OAuth2EdgeTest --- .../org/thingsboard/server/edge/NotificationEdgeTest.java | 1 - .../java/org/thingsboard/server/edge/OAuth2EdgeTest.java | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/NotificationEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/NotificationEdgeTest.java index 890ec00913..6d4ebb3676 100644 --- a/application/src/test/java/org/thingsboard/server/edge/NotificationEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/NotificationEdgeTest.java @@ -18,7 +18,6 @@ package org.thingsboard.server.edge; import com.google.protobuf.AbstractMessage; import org.junit.Assert; import org.junit.Test; -import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; diff --git a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java index c25410b562..beae36718d 100644 --- a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java @@ -59,12 +59,7 @@ public class OAuth2EdgeTest extends AbstractEdgeTest { oAuth2Info.setEnabled(false); oAuth2Info.setEdgeEnabled(false); doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); - Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg); - oAuth2UpdateMsg = (OAuth2UpdateMsg) latestMessage; - result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true); - Assert.assertEquals(oAuth2Info, result); + Assert.assertFalse(edgeImitator.waitForMessages(5)); edgeImitator.ignoreType(OAuth2UpdateMsg.class); loginTenantAdmin(); From 094f840f119b0db11997ab8c5828901b53ff3afc Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 11 Jul 2024 14:26:59 +0200 Subject: [PATCH 5/5] JpaAlarmDao debug log added --- .../alarm/AlarmCreateOrUpdateActiveRequest.java | 4 ++++ .../common/data/alarm/AlarmUpdateRequest.java | 4 ++++ .../server/dao/sql/alarm/JpaAlarmDao.java | 15 ++++++++++++--- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java index c39c603a9e..4cf3d5a790 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; +import lombok.ToString; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; @@ -53,9 +54,12 @@ public class AlarmCreateOrUpdateActiveRequest implements AlarmModificationReques private long startTs; @Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") private long endTs; + + @ToString.Exclude @NoXss @Schema(description = "JSON object with alarm details") private JsonNode details; + @Valid @Schema(description = "JSON object with propagation details") private AlarmPropagationInfo propagation; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java index 8eb418d6dc..1556e5fa73 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; +import lombok.ToString; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; @@ -47,9 +48,12 @@ public class AlarmUpdateRequest implements AlarmModificationRequest { private long startTs; @Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") private long endTs; + + @ToString.Exclude @NoXss @Schema(description = "JSON object with alarm details") private JsonNode details; + @Valid @Schema(description = "JSON object with propagation details") private AlarmPropagationInfo propagation; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index b0bf2cc666..133eb70521 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -342,9 +342,12 @@ public class JpaAlarmDao extends JpaAbstractDao implements A @Override public AlarmApiCallResult createOrUpdateActiveAlarm(AlarmCreateOrUpdateActiveRequest request, boolean alarmCreationEnabled) { + UUID tenantUUID = request.getTenantId().getId(); + log.debug("[{}] createOrUpdateActiveAlarm [{}] {}", tenantUUID, alarmCreationEnabled, request); + AlarmPropagationInfo ap = getSafePropagationInfo(request.getPropagation()); return toAlarmApiResult(alarmRepository.createOrUpdateActiveAlarm( - request.getTenantId().getId(), + tenantUUID, request.getCustomerId() != null ? request.getCustomerId().getId() : CustomerId.NULL_UUID, request.getEdgeAlarmId() != null ? request.getEdgeAlarmId().getId() : UUID.randomUUID(), System.currentTimeMillis(), @@ -364,10 +367,14 @@ public class JpaAlarmDao extends JpaAbstractDao implements A @Override public AlarmApiCallResult updateAlarm(AlarmUpdateRequest request) { + UUID tenantUUID = request.getTenantId().getId(); + UUID alarmUUID = request.getAlarmId().getId(); + log.debug("[{}][{}] updateAlarm {}", tenantUUID, alarmUUID, request); + AlarmPropagationInfo ap = getSafePropagationInfo(request.getPropagation()); return toAlarmApiResult(alarmRepository.updateAlarm( - request.getTenantId().getId(), - request.getAlarmId().getId(), + tenantUUID, + alarmUUID, request.getSeverity().name(), request.getStartTs(), request.getEndTs(), getDetailsAsString(request.getDetails()), @@ -380,11 +387,13 @@ public class JpaAlarmDao extends JpaAbstractDao implements A @Override public AlarmApiCallResult acknowledgeAlarm(TenantId tenantId, AlarmId id, long ackTs) { + log.debug("[{}][{}] acknowledgeAlarm [{}]", tenantId, id, ackTs); return toAlarmApiResult(alarmRepository.acknowledgeAlarm(tenantId.getId(), id.getId(), ackTs)); } @Override public AlarmApiCallResult clearAlarm(TenantId tenantId, AlarmId id, long clearTs, JsonNode details) { + log.debug("[{}][{}] clearAlarm [{}]", tenantId, id, clearTs); return toAlarmApiResult(alarmRepository.clearAlarm(tenantId.getId(), id.getId(), clearTs, details != null ? getDetailsAsString(details) : null)); }