Tests for Rule Engine component lifecycle event notification rule; improvements

This commit is contained in:
ViacheslavKlimov 2023-02-02 14:15:54 +02:00
parent ae709351ce
commit bbaaa6b972
10 changed files with 173 additions and 21 deletions

View File

@ -20,7 +20,6 @@ import org.thingsboard.server.actors.TbActor;
import org.thingsboard.server.actors.TbActorCtx; import org.thingsboard.server.actors.TbActorCtx;
import org.thingsboard.server.actors.TbActorId; import org.thingsboard.server.actors.TbActorId;
import org.thingsboard.server.actors.TbEntityActorId; import org.thingsboard.server.actors.TbEntityActorId;
import org.thingsboard.server.actors.service.ComponentActor;
import org.thingsboard.server.actors.service.ContextBasedCreator; import org.thingsboard.server.actors.service.ContextBasedCreator;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -30,7 +29,7 @@ import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg; import org.thingsboard.server.common.msg.queue.QueueToRuleEngineMsg;
public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMessageProcessor> { public class RuleChainActor extends RuleEngineComponentActor<RuleChainId, RuleChainActorMessageProcessor> {
private final RuleChain ruleChain; private final RuleChain ruleChain;
@ -106,6 +105,11 @@ public class RuleChainActor extends ComponentActor<RuleChainId, RuleChainActorMe
return ruleChain.getId(); return ruleChain.getId();
} }
@Override
protected String getRuleChainName() {
return ruleChain.getName();
}
@Override @Override
protected long getErrorPersistFrequency() { protected long getErrorPersistFrequency() {
return systemContext.getRuleChainErrorPersistFrequency(); return systemContext.getRuleChainErrorPersistFrequency();

View File

@ -0,0 +1,43 @@
/**
* Copyright © 2016-2022 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.actors.ruleChain;
import org.thingsboard.server.actors.ActorSystemContext;
import org.thingsboard.server.actors.service.ComponentActor;
import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
public abstract class RuleEngineComponentActor<T extends EntityId, P extends ComponentMsgProcessor<T>> extends ComponentActor<T, P> {
public RuleEngineComponentActor(ActorSystemContext systemContext, TenantId tenantId, T id) {
super(systemContext, tenantId, id);
}
@Override
protected void logLifecycleEvent(ComponentLifecycleEvent event, Exception e) {
super.logLifecycleEvent(event, e);
systemContext.getNotificationRuleProcessingService().process(tenantId, getRuleChainId(), getRuleChainName(),
id, processor.getComponentName(), event, e);
}
protected abstract RuleChainId getRuleChainId();
protected abstract String getRuleChainName();
}

View File

@ -21,7 +21,6 @@ import org.thingsboard.server.actors.TbActor;
import org.thingsboard.server.actors.TbActorCtx; import org.thingsboard.server.actors.TbActorCtx;
import org.thingsboard.server.actors.TbActorId; import org.thingsboard.server.actors.TbActorId;
import org.thingsboard.server.actors.TbEntityActorId; import org.thingsboard.server.actors.TbEntityActorId;
import org.thingsboard.server.actors.service.ComponentActor;
import org.thingsboard.server.actors.service.ContextBasedCreator; import org.thingsboard.server.actors.service.ContextBasedCreator;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeId;
@ -32,7 +31,7 @@ import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
@Slf4j @Slf4j
public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> { public class RuleNodeActor extends RuleEngineComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> {
private final String ruleChainName; private final String ruleChainName;
private final RuleChainId ruleChainId; private final RuleChainId ruleChainId;
@ -138,6 +137,11 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa
return ruleChainId; return ruleChainId;
} }
@Override
protected String getRuleChainName() {
return ruleChainName;
}
@Override @Override
protected long getErrorPersistFrequency() { protected long getErrorPersistFrequency() {
return systemContext.getRuleNodeErrorPersistFrequency(); return systemContext.getRuleNodeErrorPersistFrequency();

View File

@ -23,7 +23,6 @@ import org.thingsboard.server.actors.TbRuleNodeUpdateException;
import org.thingsboard.server.actors.shared.ComponentMsgProcessor; import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
import org.thingsboard.server.actors.stats.StatsPersistMsg; import org.thingsboard.server.actors.stats.StatsPersistMsg;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg;
@ -181,13 +180,10 @@ public abstract class ComponentActor<T extends EntityId, P extends ComponentMsgP
logLifecycleEvent(event, null); logLifecycleEvent(event, null);
} }
private void logLifecycleEvent(ComponentLifecycleEvent event, Exception e) { protected void logLifecycleEvent(ComponentLifecycleEvent event, Exception e) {
systemContext.persistLifecycleEvent(tenantId, id, event, e); systemContext.persistLifecycleEvent(tenantId, id, event, e);
systemContext.getNotificationRuleProcessingService().process(tenantId, getRuleChainId(), id, processor.getComponentName(), event, e);
} }
protected abstract RuleChainId getRuleChainId();
protected abstract long getErrorPersistFrequency(); protected abstract long getErrorPersistFrequency();
} }

View File

@ -100,9 +100,10 @@ public class DefaultNotificationRuleProcessingService implements NotificationRul
} }
@Override @Override
public void process(TenantId tenantId, RuleChainId ruleChainId, EntityId componentId, String componentName, ComponentLifecycleEvent eventType, Exception error) { public void process(TenantId tenantId, RuleChainId ruleChainId, String ruleChainName, EntityId componentId, String componentName, ComponentLifecycleEvent eventType, Exception error) {
RuleEngineComponentLifecycleEventTriggerObject triggerObject = RuleEngineComponentLifecycleEventTriggerObject.builder() RuleEngineComponentLifecycleEventTriggerObject triggerObject = RuleEngineComponentLifecycleEventTriggerObject.builder()
.ruleChainId(ruleChainId) .ruleChainId(ruleChainId)
.ruleChainName(ruleChainName)
.componentId(componentId) .componentId(componentId)
.componentName(componentName) .componentName(componentName)
.eventType(eventType) .eventType(eventType)

View File

@ -28,6 +28,7 @@ public interface NotificationRuleProcessingService {
void process(TenantId tenantId, Alarm alarm, boolean deleted); void process(TenantId tenantId, Alarm alarm, boolean deleted);
void process(TenantId tenantId, RuleChainId ruleChainId, EntityId componentId, String componentName, ComponentLifecycleEvent eventType, Exception error); void process(TenantId tenantId, RuleChainId ruleChainId, String ruleChainName,
EntityId componentId, String componentName, ComponentLifecycleEvent eventType, Exception error);
} }

View File

@ -15,9 +15,11 @@
*/ */
package org.thingsboard.server.service.notification.rule.trigger; package org.thingsboard.server.service.notification.rule.trigger;
import com.google.common.base.Strings;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
@ -29,7 +31,6 @@ import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineCo
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.service.notification.rule.trigger.RuleEngineComponentLifecycleEventTriggerProcessor.RuleEngineComponentLifecycleEventTriggerObject; import org.thingsboard.server.service.notification.rule.trigger.RuleEngineComponentLifecycleEventTriggerProcessor.RuleEngineComponentLifecycleEventTriggerObject;
import java.util.Optional;
import java.util.Set; import java.util.Set;
@Service @Service
@ -72,13 +73,24 @@ public class RuleEngineComponentLifecycleEventTriggerProcessor implements Notifi
public NotificationInfo constructNotificationInfo(RuleEngineComponentLifecycleEventTriggerObject triggerObject, RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig triggerConfig) { public NotificationInfo constructNotificationInfo(RuleEngineComponentLifecycleEventTriggerObject triggerObject, RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig triggerConfig) {
return RuleEngineComponentLifecycleEventNotificationInfo.builder() return RuleEngineComponentLifecycleEventNotificationInfo.builder()
.ruleChainId(triggerObject.getRuleChainId()) .ruleChainId(triggerObject.getRuleChainId())
.ruleChainName(triggerObject.getRuleChainName())
.componentId(triggerObject.getComponentId()) .componentId(triggerObject.getComponentId())
.componentName(triggerObject.getComponentName()) .componentName(triggerObject.getComponentName())
.eventType(triggerObject.getEventType()) .eventType(triggerObject.getEventType())
.error(Optional.ofNullable(triggerObject.getError()).map(Throwable::getMessage).orElse(null)) .error(getErrorMsg(triggerObject.getError()))
.build(); .build();
} }
private String getErrorMsg(Exception error) {
String errorMsg = error != null ? error.getMessage() : null;
errorMsg = Strings.nullToEmpty(errorMsg);
int lengthLimit = 150;
if (errorMsg.length() > lengthLimit) {
errorMsg = StringUtils.substring(errorMsg, 0, lengthLimit + 1).trim() + "[...]";
}
return errorMsg;
}
@Override @Override
public NotificationRuleTriggerType getTriggerType() { public NotificationRuleTriggerType getTriggerType() {
return NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT; return NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT;
@ -88,6 +100,7 @@ public class RuleEngineComponentLifecycleEventTriggerProcessor implements Notifi
@Builder @Builder
public static class RuleEngineComponentLifecycleEventTriggerObject { public static class RuleEngineComponentLifecycleEventTriggerObject {
private final RuleChainId ruleChainId; private final RuleChainId ruleChainId;
private final String ruleChainName;
private final EntityId componentId; private final EntityId componentId;
private final String componentName; private final String componentName;
private final ComponentLifecycleEvent eventType; private final ComponentLifecycleEvent eventType;

View File

@ -24,6 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.data.util.Pair; import org.springframework.data.util.Pair;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.rule.engine.debug.TbMsgGeneratorNode;
import org.thingsboard.rule.engine.debug.TbMsgGeneratorNodeConfiguration;
import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfile;
@ -40,6 +42,7 @@ import org.thingsboard.server.common.data.device.profile.AlarmRule;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm; import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec; import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec;
import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationRuleId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.Notification;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
@ -53,13 +56,19 @@ import org.thingsboard.server.common.data.notification.rule.NotificationRuleInfo
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.EntityActionNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.rule.trigger.EntityActionNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget; import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.query.BooleanFilterPredicate; import org.thingsboard.server.common.data.query.BooleanFilterPredicate;
import org.thingsboard.server.common.data.query.EntityKeyValueType; import org.thingsboard.server.common.data.query.EntityKeyValueType;
import org.thingsboard.server.common.data.query.FilterPredicateValue; import org.thingsboard.server.common.data.query.FilterPredicateValue;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.common.data.script.ScriptLanguage;
import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.notification.NotificationRequestService; import org.thingsboard.server.dao.notification.NotificationRequestService;
@ -130,7 +139,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
getWsClient().waitForUpdate(true); getWsClient().waitForUpdate(true);
Notification notification = getWsClient().getLastDataUpdate().getUpdate(); Notification notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getSubject()).isEqualTo("ADDED: DEVICE [" + device.getId() + "]"); assertThat(notification.getSubject()).isEqualTo("added: DEVICE [" + device.getId() + "]");
assertThat(notification.getText()).isEqualTo("User: " + TENANT_ADMIN_EMAIL); assertThat(notification.getText()).isEqualTo("User: " + TENANT_ADMIN_EMAIL);
@ -140,7 +149,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
getWsClient().waitForUpdate(true); getWsClient().waitForUpdate(true);
notification = getWsClient().getLastDataUpdate().getUpdate(); notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getSubject()).isEqualTo("UPDATED: DEVICE [" + device.getId() + "]"); assertThat(notification.getSubject()).isEqualTo("updated: DEVICE [" + device.getId() + "]");
getWsClient().registerWaitForUpdate(); getWsClient().registerWaitForUpdate();
@ -148,7 +157,7 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
getWsClient().waitForUpdate(true); getWsClient().waitForUpdate(true);
notification = getWsClient().getLastDataUpdate().getUpdate(); notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getSubject()).isEqualTo("DELETED: DEVICE [" + device.getId() + "]"); assertThat(notification.getSubject()).isEqualTo("deleted: DEVICE [" + device.getId() + "]");
} }
@Test @Test
@ -307,6 +316,48 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
assertThat(findNotificationRequests(EntityType.ALARM).getData()).filteredOn(NotificationRequest::isScheduled).isEmpty(); assertThat(findNotificationRequests(EntityType.ALARM).getData()).filteredOn(NotificationRequest::isScheduled).isEmpty();
} }
@Test
public void testNotificationRuleProcessing_ruleEngineComponentLifecycleEvent_ruleNodeStartError() {
String subject = "Rule Node '${componentName}' in Rule Chain '${ruleChainName}' failed to start";
String text = "The error: ${error}";
NotificationTemplate template = createNotificationTemplate(NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT, subject, text, NotificationDeliveryMethod.PUSH);
NotificationRule rule = new NotificationRule();
rule.setName("Rule node start-up failures in my rule chain");
rule.setTemplateId(template.getId());
rule.setTriggerType(NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT);
RuleChain ruleChain = createEmptyRuleChain("My Rule Chain");
var triggerConfig = new RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig();
triggerConfig.setRuleChains(Set.of(ruleChain.getUuidId()));
triggerConfig.setRuleChainEvents(Set.of(ComponentLifecycleEvent.STARTED));
triggerConfig.setOnlyRuleChainLifecycleFailures(true);
triggerConfig.setTrackRuleNodeEvents(true);
triggerConfig.setRuleNodeEvents(Set.of(ComponentLifecycleEvent.STARTED));
triggerConfig.setOnlyRuleNodeLifecycleFailures(true);
rule.setTriggerConfig(triggerConfig);
NotificationTarget target = createNotificationTarget(tenantAdminUserId);
DefaultNotificationRuleRecipientsConfig recipientsConfig = new DefaultNotificationRuleRecipientsConfig();
recipientsConfig.setTriggerType(NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT);
recipientsConfig.setTargets(List.of(target.getUuidId()));
rule.setRecipientsConfig(recipientsConfig);
rule = saveNotificationRule(rule);
getWsClient().subscribeForUnreadNotifications(10).waitForReply(true);
getWsClient().registerWaitForUpdate();
addRuleNodeWithError(ruleChain.getId(), "My generator");
getWsClient().waitForUpdate(10000, true);
Notification notification = getWsClient().getLastDataUpdate().getUpdate();
assertThat(notification.getType()).isEqualTo(NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT);
assertThat(notification.getSubject()).isEqualTo("Rule Node 'My generator' in Rule Chain 'My Rule Chain' failed to start");
assertThat(notification.getText()).startsWith("The error: Can't compile script");
}
@Test @Test
public void testNotificationRuleInfo() throws Exception { public void testNotificationRuleInfo() throws Exception {
NotificationDeliveryMethod[] deliveryMethods = {NotificationDeliveryMethod.PUSH, NotificationDeliveryMethod.EMAIL}; NotificationDeliveryMethod[] deliveryMethods = {NotificationDeliveryMethod.PUSH, NotificationDeliveryMethod.EMAIL};
@ -368,6 +419,41 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest {
return deviceProfile; return deviceProfile;
} }
private RuleChain createEmptyRuleChain(String name) {
RuleChain ruleChain = new RuleChain();
ruleChain.setName(name);
ruleChain.setTenantId(tenantId);
ruleChain.setRoot(false);
ruleChain.setDebugMode(false);
ruleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class);
RuleChainMetaData metaData = new RuleChainMetaData();
metaData.setRuleChainId(ruleChain.getId());
metaData.setNodes(List.of());
metaData = doPost("/api/ruleChain/metadata", metaData, RuleChainMetaData.class);
return ruleChain;
}
private RuleNode addRuleNodeWithError(RuleChainId ruleChainId, String name) {
RuleChainMetaData metaData = new RuleChainMetaData();
metaData.setRuleChainId(ruleChainId);
RuleNode generatorNodeWithError = new RuleNode();
generatorNodeWithError.setName(name);
generatorNodeWithError.setType(TbMsgGeneratorNode.class.getName());
TbMsgGeneratorNodeConfiguration generatorNodeConfiguration = new TbMsgGeneratorNodeConfiguration();
generatorNodeConfiguration.setScriptLang(ScriptLanguage.JS);
generatorNodeConfiguration.setPeriodInSeconds(1000);
generatorNodeConfiguration.setMsgCount(1);
generatorNodeConfiguration.setJsScript("[return");
generatorNodeWithError.setConfiguration(mapper.valueToTree(generatorNodeConfiguration));
metaData.setNodes(List.of(generatorNodeWithError));
metaData.setFirstNodeIndex(0);
metaData = doPost("/api/ruleChain/metadata", metaData, RuleChainMetaData.class);
return metaData.getNodes().get(0);
}
private NotificationRule saveNotificationRule(NotificationRule notificationRule) { private NotificationRule saveNotificationRule(NotificationRule notificationRule) {
return doPost("/api/notification/rule", notificationRule, NotificationRule.class); return doPost("/api/notification/rule", notificationRule, NotificationRule.class);
} }

View File

@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.notification.template.NotificationTemp
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig; import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import org.thingsboard.server.common.data.notification.template.PushDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.PushDeliveryMethodNotificationTemplate;
import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -94,9 +95,10 @@ public class NotificationProcessingContext {
} }
public <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, Map<String, String> templateContext) { public <T extends DeliveryMethodNotificationTemplate> T getProcessedTemplate(NotificationDeliveryMethod deliveryMethod, Map<String, String> templateContext) {
if (request.getInfo() != null && deliveryMethod != NotificationDeliveryMethod.PUSH) { // for push notifications we are processing template from info on each serialization NotificationInfo info = request.getInfo();
if (info != null && deliveryMethod != NotificationDeliveryMethod.PUSH) { // for push notifications we are processing template from info on each serialization
templateContext = new HashMap<>(templateContext); templateContext = new HashMap<>(templateContext);
templateContext.putAll(request.getInfo().getTemplateData()); templateContext.putAll(info.getTemplateData());
} }
T template = (T) templates.get(deliveryMethod).copy(); T template = (T) templates.get(deliveryMethod).copy();
@ -114,7 +116,7 @@ public class NotificationProcessingContext {
if (buttonConfig.isPresent()) { if (buttonConfig.isPresent()) {
JsonNode link = buttonConfig.get().get("link"); JsonNode link = buttonConfig.get().get("link");
if (link != null && link.isTextual()) { if (link != null && link.isTextual()) {
link = new TextNode(processTemplate(link.asText(), templateContext, request.getInfo().getTemplateData())); link = new TextNode(processTemplate(link.asText(), templateContext, info != null ? info.getTemplateData() : Collections.emptyMap()));
buttonConfig.get().set("link", link); buttonConfig.get().set("link", link);
} }
} }

View File

@ -20,6 +20,7 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
@ -33,21 +34,22 @@ import java.util.Map;
public class RuleEngineComponentLifecycleEventNotificationInfo implements NotificationInfo { public class RuleEngineComponentLifecycleEventNotificationInfo implements NotificationInfo {
private RuleChainId ruleChainId; private RuleChainId ruleChainId;
private String ruleChainName;
private EntityId componentId; private EntityId componentId;
private String componentName; private String componentName;
private ComponentLifecycleEvent eventType; private ComponentLifecycleEvent eventType;
private String error; private String error;
// TODO: add rule chain name
@Override @Override
public Map<String, String> getTemplateData() { public Map<String, String> getTemplateData() {
return Map.of( return Map.of(
"ruleChainId", ruleChainId.toString(), "ruleChainId", ruleChainId.toString(),
"ruleChainName", ruleChainName,
"componentId", componentId.toString(), "componentId", componentId.toString(),
"componentType", componentId.getEntityType().name(), "componentType", componentId.getEntityType().name(),
"componentName", componentName, "componentName", componentName,
"eventType", eventType.name(), "eventType", eventType.name(),
"error", Strings.nullToEmpty(error) "error", error
); );
} }