* GH-2880: Handle `Pausable` in Control Bus Fixes https://github.com/spring-projects/spring-integration/issues/2880 * Refactor `ControlBusMethodFilter` to handle `Pausable` managed operations * Optimize and internal `ControlBusMethodFilter.filter()` logic to rely on the `MergedAnnotations` * Modify `EnableIntegrationTests` to test new functionality and document the feature * * `ControlBusMethodFilter` to deal with plain `Lifecycle` impls as well
81 lines
3.3 KiB
Plaintext
81 lines
3.3 KiB
Plaintext
[[control-bus]]
|
|
=== Control Bus
|
|
|
|
As described in the https://www.enterpriseintegrationpatterns.com/[_Enterprise Integration Patterns_] (EIP) book, the idea behind the control bus is that the same messaging system can be used for monitoring and managing the components within the framework as is used for "`application-level`" messaging.
|
|
In Spring Integration, we build upon the adapters described above so that you can send messages as a means of invoking exposed operations.
|
|
|
|
The following example shows how to configure a control bus with XML:
|
|
|
|
====
|
|
[source,xml]
|
|
----
|
|
<int:control-bus input-channel="operationChannel"/>
|
|
----
|
|
====
|
|
|
|
The control bus has an input channel that can be accessed for invoking operations on the beans in the application context.
|
|
It also has all the common properties of a service activating endpoint.
|
|
For example, you can specify an output channel if the result of the operation has a return value that you want to send on to a downstream channel.
|
|
|
|
The control bus runs messages on the input channel as Spring Expression Language (SpEL) expressions.
|
|
It takes a message, compiles the body to an expression, adds some context, and then runs it.
|
|
The default context supports any method that has been annotated with `@ManagedAttribute` or `@ManagedOperation`.
|
|
It also supports the methods on Spring's `Lifecycle` interface (and its `Pausable` extension since version 5.2), and it supports methods that are used to configure several of Spring's `TaskExecutor` and `TaskScheduler` implementations.
|
|
The simplest way to ensure that your own methods are available to the control bus is to use the `@ManagedAttribute` or `@ManagedOperation` annotations.
|
|
Since those annotations are also used for exposing methods to a JMX MBean registry, they offer a convenient by-product: Often, the same types of operations you want to expose to the control bus are reasonable for exposing through JMX).
|
|
Resolution of any particular instance within the application context is achieved in the typical SpEL syntax.
|
|
To do so, provide the bean name with the SpEL prefix for beans (`@`).
|
|
For example, to execute a method on a Spring Bean, a client could send a message to the operation channel as follows:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
Message operation = MessageBuilder.withPayload("@myServiceBean.shutdown()").build();
|
|
operationChannel.send(operation)
|
|
----
|
|
====
|
|
|
|
The root of the context for the expression is the `Message` itself, so you also have access to the `payload` and `headers` as variables within your expression.
|
|
This is consistent with all the other expression support in Spring Integration endpoints.
|
|
|
|
With Java annotations, you can configured the control bus as follows:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
@Bean
|
|
@ServiceActivator(inputChannel = "operationChannel")
|
|
public ExpressionControlBusFactoryBean controlBus() {
|
|
return new ExpressionControlBusFactoryBean();
|
|
}
|
|
----
|
|
====
|
|
|
|
Similarly, you can configure Java DSL flow definitions as follows:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
@Bean
|
|
public IntegrationFlow controlBusFlow() {
|
|
return IntegrationFlows.from("controlBus")
|
|
.controlBus()
|
|
.get();
|
|
}
|
|
----
|
|
====
|
|
|
|
If you prefer to use lambdas with automatic `DirectChannel` creation, you can create a control bus as follows:
|
|
|
|
====
|
|
[source,java]
|
|
----
|
|
@Bean
|
|
public IntegrationFlow controlBus() {
|
|
return IntegrationFlowDefinition::controlBus;
|
|
}
|
|
----
|
|
====
|
|
|
|
In this case, the channel is named `controlBus.input`.
|