Integration Graph
Starting with version 4.3, Spring Integration provides access to an application’s runtime object model, which can, optionally, include component metrics.
It is exposed as a graph, which may be used to visualize the current state of the integration application.
The o.s.i.support.management.graph
package contains all the required classes to collect, build, and render the runtime state of Spring Integration components as a single tree-like Graph
object.
The IntegrationGraphServer
should be declared as a bean to build, retrieve, and refresh the Graph
object.
The resulting Graph
object can be serialized to any format, although JSON is flexible and convenient to parse and represent on the client side.
A Spring Integration application with only the default components would expose a graph as follows:
{
"contentDescriptor" : {
"providerVersion" : "6.4.0",
"providerFormatVersion" : 1.2,
"provider" : "spring-integration",
"name" : "myAppName:1.0"
},
"nodes" : [ {
"nodeId" : 1,
"componentType" : "null-channel",
"integrationPatternType" : "null_channel",
"integrationPatternCategory" : "messaging_channel",
"properties" : { },
"sendTimers" : {
"successes" : {
"count" : 1,
"mean" : 0.0,
"max" : 0.0
},
"failures" : {
"count" : 0,
"mean" : 0.0,
"max" : 0.0
}
},
"receiveCounters" : {
"successes" : 0,
"failures" : 0
},
"name" : "nullChannel"
}, {
"nodeId" : 2,
"componentType" : "publish-subscribe-channel",
"integrationPatternType" : "publish_subscribe_channel",
"integrationPatternCategory" : "messaging_channel",
"properties" : { },
"sendTimers" : {
"successes" : {
"count" : 1,
"mean" : 7.807002,
"max" : 7.807002
},
"failures" : {
"count" : 0,
"mean" : 0.0,
"max" : 0.0
}
},
"name" : "errorChannel"
}, {
"nodeId" : 3,
"componentType" : "logging-channel-adapter",
"integrationPatternType" : "outbound_channel_adapter",
"integrationPatternCategory" : "messaging_endpoint",
"properties" : { },
"output" : null,
"input" : "errorChannel",
"sendTimers" : {
"successes" : {
"count" : 1,
"mean" : 6.742722,
"max" : 6.742722
},
"failures" : {
"count" : 0,
"mean" : 0.0,
"max" : 0.0
}
},
"name" : "errorLogger"
} ],
"links" : [ {
"from" : 2,
"to" : 3,
"type" : "input"
} ]
}
Version 5.2 deprecated the legacy metrics in favor of Micrometer meters as discussed Metrics Management. The legacy metrics were removed in Version 5.4 and will no longer appear in the graph. |
In the preceding example, the graph consists of three top-level elements.
The contentDescriptor
graph element contains general information about the application providing the data.
The name
can be customized on the IntegrationGraphServer
bean or in the spring.application.name
application context environment property.
Other properties are provided by the framework and let you distinguish a similar model from other sources.
The links
graph element represents connections between nodes from the nodes
graph element and, therefore, between integration components in the source Spring Integration application.
For example, from a MessageChannel
to an EventDrivenConsumer
with some MessageHandler
or from an AbstractReplyProducingMessageHandler
to a MessageChannel
.
For convenience and to let you determine a link’s purpose, the model includes the type
attribute.
The possible types are:
-
input
: Identifies the direction fromMessageChannel
to the endpoint,inputChannel
, orrequestChannel
property -
output
: The direction from theMessageHandler
,MessageProducer
, orSourcePollingChannelAdapter
to theMessageChannel
through anoutputChannel
orreplyChannel
property -
error
: FromMessageHandler
onPollingConsumer
orMessageProducer
orSourcePollingChannelAdapter
to theMessageChannel
through anerrorChannel
property; -
discard
: FromDiscardingMessageHandler
(such asMessageFilter
) to theMessageChannel
through anerrorChannel
property. -
route
: FromAbstractMappingMessageRouter
(such asHeaderValueRouter
) to theMessageChannel
. Similar tooutput
but determined at run-time. Maybe a configured channel mapping or a dynamically resolved channel. Routers typically retain only up to 100 dynamic routes for this purpose, but you can modify this value by setting thedynamicChannelLimit
property.
The information from this element can be used by a visualization tool to render connections between nodes from the nodes
graph element, where the from
and to
numbers represent the value from the nodeId
property of the linked nodes.
For example, the link
element can be used to determine the proper port
on the target node.
The following “text image” shows the relationships between the types:
+---(discard) | +----o----+ | | | | | | (input)--o o---(output) | | | | | | +----o----+ | +---(error)
The nodes
graph element is perhaps the most interesting, because its elements contain not only the runtime components with their componentType
instances and name
values but can also optionally contain metrics exposed by the component.
Node elements contain various properties that are generally self-explanatory.
For example, expression-based components include the expression
property that contains the primary expression string for the component.
To enable the metrics, add an @EnableIntegrationManagement
to a @Configuration
class or add an <int:management/>
element to your XML configuration.
See Metrics and Management for complete information.
The nodeId
represents a unique incremental identifier to let you distinguish one component from another.
It is also used in the links
element to represent a relationship (connection) of this component to others, if any.
The input
and output
attributes are for the inputChannel
and outputChannel
properties of the AbstractEndpoint
, MessageHandler
, SourcePollingChannelAdapter
, or MessageProducerSupport
.
See the next section for more information.
Starting with version 5.1, the IntegrationGraphServer
accepts a Function<NamedComponent, Map<String, Object>> additionalPropertiesCallback
for population of additional properties on the IntegrationNode
for a particular NamedComponent
.
For example, you can expose the SmartLifecycle
autoStartup
and running
properties into the target graph:
server.setAdditionalPropertiesCallback(namedComponent -> {
Map<String, Object> properties = null;
if (namedComponent instanceof SmartLifecycle) {
SmartLifecycle smartLifecycle = (SmartLifecycle) namedComponent;
properties = new HashMap<>();
properties.put("auto-startup", smartLifecycle.isAutoStartup());
properties.put("running", smartLifecycle.isRunning());
}
return properties;
});
Graph Runtime Model
Spring Integration components have various levels of complexity.
For example, any polled MessageSource
also has a SourcePollingChannelAdapter
and a MessageChannel
to which to periodically send messages from the source data.
Other components might be middleware request-reply components (such as JmsOutboundGateway
) with a consuming AbstractEndpoint
to subscribe to (or poll) the requestChannel
(input
) for messages, and a replyChannel
(output
) to produce a reply message to send downstream.
Meanwhile, any MessageProducerSupport
implementation (such as ApplicationEventListeningMessageProducer
) wraps some source protocol listening logic and sends messages to the outputChannel
.
Within the graph, Spring Integration components are represented by using the IntegrationNode
class hierarchy, which you can find in the o.s.i.support.management.graph
package.
For example, you can use the ErrorCapableDiscardingMessageHandlerNode
for the AggregatingMessageHandler
(because it has a discardChannel
option) and can produce errors when consuming from a PollableChannel
by using a PollingConsumer
.
Another example is CompositeMessageHandlerNode
— for a MessageHandlerChain
when subscribed to a SubscribableChannel
by using an EventDrivenConsumer
.
The @MessagingGateway (see Messaging Gateways) provides nodes for each of its method, where the name attribute is based on the gateway’s bean name and the short method signature.
Consider the following example of a gateway:
|
@MessagingGateway(defaultRequestChannel = "four")
public interface Gate {
void foo(String foo);
void foo(Integer foo);
void bar(String bar);
}
The preceding gateway produces nodes similar to the following:
{
"nodeId" : 10,
"name" : "gate.bar(class java.lang.String)",
"stats" : null,
"componentType" : "gateway",
"integrationPatternType" : "gateway",
"integrationPatternCategory" : "messaging_endpoint",
"output" : "four",
"errors" : null
},
{
"nodeId" : 11,
"name" : "gate.foo(class java.lang.String)",
"stats" : null,
"componentType" : "gateway",
"integrationPatternType" : "gateway",
"integrationPatternCategory" : "messaging_endpoint",
"output" : "four",
"errors" : null
},
{
"nodeId" : 12,
"name" : "gate.foo(class java.lang.Integer)",
"stats" : null,
"componentType" : "gateway",
"integrationPatternType" : "gateway",
"integrationPatternCategory" : "messaging_endpoint",
"output" : "four",
"errors" : null
}
You can use this IntegrationNode
hierarchy for parsing the graph model on the client side as well as to understand the general Spring Integration runtime behavior.
See also Programming Tips and Tricks for more information.
Version 5.3 introduced an IntegrationPattern
abstraction and all out-of-the-box components, which represent an Enterprise Integration Pattern (EIP), implement this abstraction and provide an IntegrationPatternType
enum value.
This information can be useful for some categorizing logic in the target application or, being exposed into the graph node, it can be used by a UI to determine how to draw the component.