diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 5357daacce..85f469a6c9 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -36,10 +36,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.ScriptEngine; -import org.thingsboard.rule.engine.flow.TbRuleChainOutputNode; -import org.thingsboard.rule.engine.flow.TbRuleChainOutputNodeConfiguration; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.tenant.DebugTbRateLimits; import org.thingsboard.server.common.data.DataConstants; @@ -71,7 +68,6 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.event.EventService; -import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.install.InstallScripts; import org.thingsboard.server.service.rule.TbRuleChainService; diff --git a/application/src/main/java/org/thingsboard/server/service/rule/DefaultTbRuleChainService.java b/application/src/main/java/org/thingsboard/server/service/rule/DefaultTbRuleChainService.java index e6d1ba1d8a..ff2599c0ff 100644 --- a/application/src/main/java/org/thingsboard/server/service/rule/DefaultTbRuleChainService.java +++ b/application/src/main/java/org/thingsboard/server/service/rule/DefaultTbRuleChainService.java @@ -23,7 +23,6 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.flow.TbRuleChainInputNode; import org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration; import org.thingsboard.rule.engine.flow.TbRuleChainOutputNode; -import org.thingsboard.rule.engine.flow.TbRuleChainOutputNodeConfiguration; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; @@ -65,14 +64,7 @@ public class DefaultTbRuleChainService implements TbRuleChainService { Set outputLabels = new TreeSet<>(); for (RuleNode ruleNode : metaData.getNodes()) { if (isOutputRuleNode(ruleNode)) { - try { - var configuration = JacksonUtil.treeToValue(ruleNode.getConfiguration(), TbRuleChainOutputNodeConfiguration.class); - if (StringUtils.isNotEmpty(configuration.getLabel())) { - outputLabels.add(configuration.getLabel()); - } - } catch (Exception e) { - log.warn("[{}][{}] Failed to decode rule node configuration", tenantId, ruleChainId, e); - } + outputLabels.add(ruleNode.getName()); } } return outputLabels; @@ -130,16 +122,15 @@ public class DefaultTbRuleChainService implements TbRuleChainService { Set confusedLabels = new HashSet<>(); Map updatedLabels = new HashMap<>(); for (RuleNodeUpdateResult update : result.getUpdatedRuleNodes()) { - var node = update.getNewRuleNode(); - if (isOutputRuleNode(node)) { + var oldNode = update.getOldRuleNode(); + var newNode = update.getNewRuleNode(); + if (isOutputRuleNode(newNode)) { try { - TbRuleChainOutputNodeConfiguration oldConf = JacksonUtil.treeToValue(update.getOldConfiguration(), TbRuleChainOutputNodeConfiguration.class); - TbRuleChainOutputNodeConfiguration newConf = JacksonUtil.treeToValue(node.getConfiguration(), TbRuleChainOutputNodeConfiguration.class); - oldLabels.add(oldConf.getLabel()); - newLabels.add(newConf.getLabel()); - if (!oldConf.getLabel().equals(newConf.getLabel())) { - String oldLabel = oldConf.getLabel(); - String newLabel = newConf.getLabel(); + oldLabels.add(oldNode.getName()); + newLabels.add(newNode.getName()); + if (!oldNode.getName().equals(newNode.getName())) { + String oldLabel = oldNode.getName(); + String newLabel = newNode.getName(); if (updatedLabels.containsKey(oldLabel) && !updatedLabels.get(oldLabel).equals(newLabel)) { confusedLabels.add(oldLabel); log.warn("[{}][{}] Can't automatically rename the label from [{}] to [{}] due to conflict [{}]", tenantId, ruleChainId, oldLabel, newLabel, updatedLabels.get(oldLabel)); @@ -149,7 +140,7 @@ public class DefaultTbRuleChainService implements TbRuleChainService { } } catch (Exception e) { - log.warn("[{}][{}][{}] Failed to decode rule node configuration", tenantId, ruleChainId, node.getId(), e); + log.warn("[{}][{}][{}] Failed to decode rule node configuration", tenantId, ruleChainId, newNode.getId(), e); } } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeUpdateResult.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeUpdateResult.java index a279533138..02f68ea5c2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeUpdateResult.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNodeUpdateResult.java @@ -27,6 +27,7 @@ import java.util.Map; @Data public class RuleNodeUpdateResult { - private final JsonNode oldConfiguration; + private final RuleNode oldRuleNode; private final RuleNode newRuleNode; + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index e1aaa31d3c..33ef74db65 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -172,10 +172,10 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC newRuleNode = ruleChainMetaData.getNodes().get(index); toAddOrUpdate.add(newRuleNode); } else { - updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode.getConfiguration(), null)); + updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode, null)); toDelete.add(existingNode); } - updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode.getConfiguration(), newRuleNode)); + updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode, newRuleNode)); } if (nodes != null) { for (RuleNode node : toAddOrUpdate) { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java index f5f75f1275..59ddc1c096 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.flow; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.EmptyNodeConfiguration; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; @@ -30,28 +31,24 @@ import org.thingsboard.server.common.msg.TbMsg; @RuleNode( type = ComponentType.FLOW, name = "output", - configClazz = TbRuleChainOutputNodeConfiguration.class, + configClazz = EmptyNodeConfiguration.class, nodeDescription = "transfers the message to the caller rule chain", nodeDetails = "Produces output of the rule chain processing. " + "The output is forwarded to the caller rule chain, as an output of the corresponding \"input\" rule node. " + - "The rule node configuration contains the \"label\" parameter. " + - "This parameter corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain. ", + "The output rule node name corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain. ", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFlowNodeRuleChainOutputConfig", outEnabled = false ) public class TbRuleChainOutputNode implements TbNode { - private TbRuleChainOutputNodeConfiguration config; - @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { - this.config = TbNodeUtils.convert(configuration, TbRuleChainOutputNodeConfiguration.class); } @Override public void onMsg(TbContext ctx, TbMsg msg) { - ctx.output(msg, config.getLabel()); + ctx.output(msg, ctx.getSelf().getName()); } @Override diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNodeConfiguration.java deleted file mode 100644 index 8d220530c3..0000000000 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNodeConfiguration.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright © 2016-2021 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.rule.engine.flow; - -import lombok.Data; -import org.thingsboard.rule.engine.api.NodeConfiguration; -import org.thingsboard.rule.engine.api.TbRelationTypes; -import org.thingsboard.server.common.data.DataConstants; - -@Data -public class TbRuleChainOutputNodeConfiguration implements NodeConfiguration { - - private String label; - - @Override - public TbRuleChainOutputNodeConfiguration defaultConfiguration() { - var result = new TbRuleChainOutputNodeConfiguration(); - result.setLabel(TbRelationTypes.SUCCESS); - return result; - } - -} diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 702fdabe6f..54fbc87f07 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -3728,13 +3728,11 @@ class RuleChainOutputComponent extends RuleNodeConfigurationComponent { return this.ruleChainOutputConfigForm; } onConfigurationSet(configuration) { - this.ruleChainOutputConfigForm = this.fb.group({ - label: [configuration ? configuration.label : null, [Validators.required]] - }); + this.ruleChainOutputConfigForm = this.fb.group({}); } } RuleChainOutputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleChainOutputComponent, deps: [{ token: i1.Store }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); -RuleChainOutputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.14", type: RuleChainOutputComponent, selector: "tb-flow-node-rule-chain-output-config", usesInheritance: true, ngImport: i0, template: "
\n \n tb.rulenode.label\n \n \n {{ 'tb.rulenode.label-required' | translate }}\n \n \n
\n", components: [{ type: i3.MatFormField, selector: "mat-form-field", inputs: ["color", "floatLabel", "appearance", "hideRequiredMarker", "hintLabel"], exportAs: ["matFormField"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.MatLabel, selector: "mat-label" }, { type: i4.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["id", "disabled", "required", "type", "value", "readonly", "placeholder", "errorStateMatcher", "aria-describedby"], exportAs: ["matInput"] }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.MatError, selector: "mat-error", inputs: ["id"] }], pipes: { "translate": i4.TranslatePipe } }); +RuleChainOutputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.14", type: RuleChainOutputComponent, selector: "tb-flow-node-rule-chain-output-config", usesInheritance: true, ngImport: i0, template: "
\n
\n
\n", directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], pipes: { "translate": i4.TranslatePipe } }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.14", ngImport: i0, type: RuleChainOutputComponent, decorators: [{ type: Component, args: [{ @@ -4191,8 +4189,7 @@ function addRuleNodeCoreLocaleEnglish(translate) { 'alarm-severity-pattern-hint': 'Hint: use ${metadataKey} ' + 'for value from metadata, $[messageKey] ' + 'for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)', - label: 'Label', - 'label-required': 'Label is required' + 'output-node-name-hint': 'The rule node name corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.' }, 'key-val': { key: 'Key',