我想使用Spring集成开发控制总线示例。作为示例,我采用了以下示例:https://github.com/spring-projects/spring-integration-samples/tree/master/basic/control-bus
我决定这样做,但是使用Java DSL。
我还阅读了以下主题:https://stackoverflow.com/a/27849287/2674303,但这对我没有帮助。
现在我有以下源代码:
@Configuration
@EnableIntegration
@IntegrationComponentScan
public class Config {
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlows.from("operationChannel")
.controlBus()
.get();
}
@Bean
@InboundChannelAdapter(channel = "adapterOutputChanel", autoStartup = "false", poller = @Poller(fixedDelay = "1000"))
public MessageSource<String> inboundAdapter() {
return new MessageSource<String>() {
@Override
public Message receive() {
return new Message() {
@Override
public String getPayload() {
return "some_output_message";
}
@Override
public MessageHeaders getHeaders() {
return null;
}
};
}
};
}
@Bean
public AbstractMessageChannel adapterOutputChanel() {
return new QueueChannel();
}
}
和应用程序:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new SpringApplication(MyApplication.class).run(args);
MessageChannel controlChannel = ctx.getBean("operationChannel", MessageChannel.class);
PollableChannel adapterOutputChanel = ctx.getBean("adapterOutputChanel", PollableChannel.class);
controlChannel.send(new GenericMessage<String>("@inboundAdapter.start()"));
adapterOutputChanel.receive(1000);
}
}
但是当我启动应用程序时,我看到以下日志:
2019-08-26 16:09:30.901 INFO 10532 --- [ main] control_bus.MyApplication : Started MyApplication in 1.248 seconds (JVM running for 2.401)
Exception in thread "main" org.springframework.messaging.MessageHandlingException: error occurred in message handler [ServiceActivator for [org.springframework.integration.handler.ExpressionCommandMessageProcessor@7351a16e] (controlBusFlow.org.springframework.integration.config.ConsumerEndpointFactoryBean#0)]; nested exception is org.springframework.expression.EvaluationException: The method 'start' is not supported by this command processor. If using the Control Bus, consider adding @ManagedOperation or @ManagedAttribute., failedMessage=GenericMessage [payload=@'inboundAdapter'.start(), headers={id=aef8f0dc-c3f5-5f7b-1a6d-7c9041f2d000, timestamp=1566824970903}]
at org.springframework.integration.support.utils.IntegrationUtils.wrapInHandlingExceptionIfNecessary(IntegrationUtils.java:189)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:186)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:132)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:105)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:73)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:453)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:401)
at control_bus.MyApplication.main(MyApplication.java:18)
Caused by: org.springframework.expression.EvaluationException: The method 'start' is not supported by this command processor. If using the Control Bus, consider adding @ManagedOperation or @ManagedAttribute.
at org.springframework.integration.handler.ExpressionCommandMessageProcessor$ExpressionCommandMethodResolver.validateMethod(ExpressionCommandMessageProcessor.java:114)
at org.springframework.integration.handler.ExpressionCommandMessageProcessor$ExpressionCommandMethodResolver.resolve(ExpressionCommandMessageProcessor.java:95)
at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:205)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:134)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:54)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:390)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:365)
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:156)
at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:151)
at org.springframework.integration.handler.ExpressionCommandMessageProcessor.processMessage(ExpressionCommandMessageProcessor.java:76)
at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:93)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:123)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:169)
... 7 more
我怎么了?
我向前走了几步,配置如下:
@Configuration
@EnableIntegration
@IntegrationComponentScan
public class Config {
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlows.from("operationChannel")
.controlBus()
.get();
}
@Bean
public AbstractMessageChannel adapterOutputChanel() {
return new QueueChannel();
}
@Bean
@InboundChannelAdapter(channel = "adapterOutputChanel", autoStartup = "false", poller = @Poller(fixedDelay = "1000"))
public MessageSource inboundAdapter() {
return new MyMessageSource();
}
public static class MyMessageSource implements MessageSource<String>, Lifecycle {
private volatile boolean started;
@Override
public Message receive() {
if (!isRunning()) {
return null;
}
return new Message() {
@Override
public String getPayload() {
return "some_output_message";
}
@Override
public MessageHeaders getHeaders() {
return null;
}
};
}
@Override
public void start() {
started = true;
}
@Override
public void stop() {
started = false;
}
@Override
public boolean isRunning() {
return started;
}
}
}
执行时:
controlChannel.send(new GenericMessage<String>("@inboundAdapter.start()"));
调用MyMessageSource#start
与stop
相同,但没有调用MyMessageSource#receive
adapterOutputChanel.receive(1000)
总是返回null
Artem Bilan回答后,我具有以下配置:
@Configuration
@EnableIntegration
@IntegrationComponentScan
public class Config {
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlows.from("operationChannel")
.controlBus()
.get();
}
@Bean
public AbstractMessageChannel adapterOutputChanel() {
return new QueueChannel();
}
@Bean
@InboundChannelAdapter(channel = "adapterOutputChanel", autoStartup = "false", poller = @Poller(fixedDelay = "1000"))
@EndpointId("myInboundAdapter")
public MessageSource inboundAdapter() {
return new MyMessageSource();
}
public static class MyMessageSource implements MessageSource<String> {
@Override
public Message receive() {
return new Message() {
@Override
public String getPayload() {
return "some_output_message";
}
@Override
public MessageHeaders getHeaders() {
return new MessageHeaders(new HashMap());
}
@Override
public String toString() {
return getPayload() + ", " + getHeaders();
}
};
}
}
}
应用程序输出:
2019-08-26 17:20:54.087 INFO 11792 --- [ main] control_bus.MyApplication : Started MyApplication in 1.526 seconds (JVM running for 2.843)
Before start:null
2019-08-26 17:20:55.093 INFO 11792 --- [ main] o.s.i.e.SourcePollingChannelAdapter : started myInboundAdapter
After start:some_output_message, {id=857f4320-5158-6daa-8a03-3a0182436a78, timestamp=1566829255098}
2019-08-26 17:20:55.098 INFO 11792 --- [ main] o.s.i.e.SourcePollingChannelAdapter : stopped myInboundAdapter
After stop:null
答案 0 :(得分:1)
根据Spring中的Java和注释配置,inboundAdapter
Bean名称(实际上是Bean方法名称)被完全分配给您声明为Bean的名称。在您的情况下,这是一种MessageSource
的实现。实际上,您确实需要处理通过该SourcePollingChannelAdapter
分配给MessageSource
的{{1}} bean的Control Bus命令。唯一的问题是我们需要找出正确的bean名称以从命令中引用它:
使用以下模式生成AbstractEndpoint Bean名称:[configurationComponentName]。[methodName]。[decapitalizedAnnotationClassShortName]。例如,前面显示的consoleSource()定义的SourcePollingChannelAdapter端点获得了myFlowConfiguration.consoleSource.inboundChannelAdapter的bean名称。另请参见端点Bean名称。
因此,我建议您采用 Endpoint Bean Names 的建议,并同时使用@InboundChannelAdapter
和@EndpointId
:
@InboundChannelAdapter
因此,您的Control Bus命令将如下所示:@Bean
@InboundChannelAdapter(channel = "adapterOutputChanel", autoStartup = "false", poller = @Poller(fixedDelay = "1000"))
@EndpointId("myInboundAdapter")
public MessageSource<String> inboundAdapter() {
更新
用于"@myInboundAdapter.start()"
接线的Java DSL变体:
MessageSource