我正在为ThingsBoard开发自定义规则节点,需要通过thingsboard.yml文件配置各种Kafka相关参数。我不想直接使用 @Value 注释,而是想将这些值读取到单独的配置类中,然后在我的自定义规则节点中使用其对象。
thingsboard.yml
custom:
node.enabled: true
config:
bootstrap.server: localhost:9092
topic.pattern: custom-*
retries: 3
batch.size: 16384
linger.ms: 0
buffer.memory: 33554432
CustomNodeConfig.java
package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import lombok.Data;
@Data
@Configuration
public class CustomNodeConfig {
@Value("${custom.node.enabled}")
private boolean enabled;
@Value("${custom.config.bootstrap.server}")
private String bootstrapServers;
@Value("${custom.config.topic.pattern}")
private String topicPattern;
@Value("${custom.config.retries}")
private int retries;
@Value("${custom.config.batch.size}")
private int batchSize;
@Value("${custom.config.linger.ms}")
private int linger;
@Value("${custom.config.buffer.memory}")
private int bufferMemory;
自定义节点.java
package com.example;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.rule.engine.api.*;
import javax.annotation.PostConstruct;
@Slf4j
@Data
@RuleNode(
type = ComponentType.EXTERNAL,
name = "Custom Node",
configClazz = CustomRuleNodeConfiguration.class,
nodeDescription = "Publish messages to Kafka server",
nodeDetails = "Outbound message will contain response fields from Kafka in the Message Metadata.",
uiResources = {"static/rulenode/rulenode-core-config.js"}
)
@Component
public class CustomNode implements TbNode {
@Autowired
private CustomNodeConfig kafkaConfig;
@PostConstruct
public void init() {
log.info("CustomRuleNode initialized with retries: {}, lingerMs: {}, bootstrapServers: {}, topicPattern: {}",
kafkaConfig.getRetries(), kafkaConfig.getLingerMs(), kafkaConfig.getBootstrapServers(), kafkaConfig.getTopicPattern());
}
@Override
public void init(TbNodeConfiguration configuration) throws TbNodeException
log.info("CustomRuleNode configuration initialized");
}
@Override
protected void onMsg(TbContext ctx, TbMsg msg) {
log.info("Received message: {}", msg.getData());
}
@Override
public void destroy() {
log.info("CustomRuleNode destroyed!");
}
}
上述实现未按预期工作,节点参与者未初始化,并在尝试 10 次重试后抛出以下异常,因为 Autowired 变量未初始化。
2024-07-04 11:36:03.060 INFO 356309 --- [-dispatcher-3-3] o.t.server.actors.TbActorMailbox : [RULE_NODE|8ad08a10-39f8-11ef-8131-5d958a56f0d4] Failed to init actor, attempt 10, going to stop attempts.
org.thingsboard.server.actors.TbActorException: Failed to init actor
at org.thingsboard.server.actors.service.ComponentActor.initProcessor(ComponentActor.java:72) ~[classes!/:3.5.1]
at org.thingsboard.server.actors.service.ComponentActor.init(ComponentActor.java:57) ~[classes!/:3.5.1]
at org.thingsboard.server.actors.TbActorMailbox.tryInit(TbActorMailbox.java:66) ~[actor-3.5.1.jar!/:3.5.1]
at org.thingsboard.server.actors.TbActorMailbox.lambda$tryInit$1(TbActorMailbox.java:85) ~[actor-3.5.1.jar!/:3.5.1]
at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426) ~[na:na]
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[na:na]
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) ~[na:na]
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) ~[na:na]
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) ~[na:na]
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183) ~[na:na]
Caused by: java.lang.NullPointerException: null
at org.thingsboard.rule.engine.custom.CustomNode.init(CustomNode.java:92) ~[rule-engine-components-3.5.1.jar!/:3.5.1]
at org.thingsboard.server.actors.ruleChain.RuleNodeActorMessageProcessor.initComponent(RuleNodeActorMessageProcessor.java:173) ~[classes!/:3.5.1]
at org.thingsboard.server.actors.ruleChain.RuleNodeActorMessageProcessor.start(RuleNodeActorMessageProcessor.java:64) ~[classes!/:3.5.1]
at org.thingsboard.server.actors.service.ComponentActor.initProcessor(ComponentActor.java:63) ~[classes!/:3.5.1]
... 9 common frames omitted
问题
我认为您无法从 TbNode 对象访问 Spring 应用程序上下文,因为整个规则链执行都是沙盒的。我认为,您能做的最好的事情就是从规则链编辑器中填写您的配置类值。