INT-4035, INT-4008: Docs for Integration Graph
JIRA: https://jira.spring.io/browse/INT-4035, https://jira.spring.io/browse/INT-4008 Polishing
This commit is contained in:
committed by
Gary Russell
parent
c6821ec387
commit
d57db56a39
@@ -21,7 +21,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.integration.http.support.DefaultHttpHeaderMapper;
|
||||
import org.springframework.integration.http.support.HttpContextUtils;
|
||||
|
||||
/**
|
||||
@@ -30,7 +29,7 @@ import org.springframework.integration.http.support.HttpContextUtils;
|
||||
*/
|
||||
class IntegrationGraphControllerRegistrarImportSelector implements ImportSelector {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(DefaultHttpHeaderMapper.class);
|
||||
private static final Log logger = LogFactory.getLog(IntegrationGraphControllerRegistrarImportSelector.class);
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
|
||||
@@ -10,8 +10,14 @@
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:annotation-driven/>
|
||||
<mvc:annotation-driven />
|
||||
|
||||
<graph-controller path="/foo"/>
|
||||
<mvc:cors>
|
||||
<mvc:mapping path="/foo"
|
||||
allowed-origins="http://foo.bar.com"
|
||||
allowed-methods="GET" />
|
||||
</mvc:cors>
|
||||
|
||||
<graph-controller path="/foo" />
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -36,10 +36,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.config.EnableIntegrationManagement;
|
||||
import org.springframework.integration.http.config.EnableIntegrationGraphController;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -53,7 +56,9 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerExecutionChain;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
|
||||
@@ -80,6 +85,7 @@ public class IntegrationGraphControllerTests {
|
||||
@Test
|
||||
public void testIntegrationGraphGet() throws Exception {
|
||||
this.mockMvc.perform(get("/testIntegration")
|
||||
.header(HttpHeaders.ORIGIN, "http://foo.bar.com")
|
||||
.accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType("application/json;charset=UTF-8"))
|
||||
@@ -99,7 +105,6 @@ public class IntegrationGraphControllerTests {
|
||||
"IntegrationGraphControllerParserTests-context.xml", getClass());
|
||||
|
||||
|
||||
|
||||
HandlerMapping handlerMapping =
|
||||
context.getBean(RequestMappingHandlerMapping.class.getName(), HandlerMapping.class);
|
||||
|
||||
@@ -108,6 +113,7 @@ public class IntegrationGraphControllerTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("GET");
|
||||
request.setRequestURI("/foo");
|
||||
request.addHeader(HttpHeaders.ORIGIN, "http://foo.bar.com");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
HandlerExecutionChain executionChain = handlerMapping.getHandler(request);
|
||||
@@ -142,8 +148,19 @@ public class IntegrationGraphControllerTests {
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@EnableIntegration
|
||||
@EnableIntegrationManagement(statsEnabled = "_org.springframework.integration.errorLogger.handler",
|
||||
countsEnabled = "!*",
|
||||
defaultLoggingEnabled = "false")
|
||||
@EnableIntegrationGraphController(path = "/testIntegration")
|
||||
public static class ContextConfiguration {
|
||||
public static class ContextConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/testIntegration/**")
|
||||
.allowedOrigins("http://foo.bar.com")
|
||||
.allowedMethods(HttpMethod.GET.name());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
191
src/reference/asciidoc/graph.adoc
Normal file
191
src/reference/asciidoc/graph.adoc
Normal file
@@ -0,0 +1,191 @@
|
||||
[[integration-graph]]
|
||||
=== 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 simple Spring Integration application with only the default components would expose a graph as follows:
|
||||
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"contentDescriptor": {
|
||||
"providerVersion": "4.3.0.RELEASE",
|
||||
"providerFormatVersion": 1.0,
|
||||
"provider": "spring-integration",
|
||||
"name": "myApplication"
|
||||
},
|
||||
"nodes": [
|
||||
{
|
||||
"nodeId": 1,
|
||||
"name": "nullChannel",
|
||||
"stats": null,
|
||||
"componentType": "channel"
|
||||
},
|
||||
{
|
||||
"nodeId": 2,
|
||||
"name": "errorChannel",
|
||||
"stats": null,
|
||||
"componentType": "publish-subscribe-channel"
|
||||
},
|
||||
{
|
||||
"nodeId": 3,
|
||||
"name": "_org.springframework.integration.errorLogger",
|
||||
"stats": {
|
||||
"duration": {
|
||||
"count": 0,
|
||||
"min": 0.0,
|
||||
"max": 0.0,
|
||||
"mean": 0.0,
|
||||
"standardDeviation": 0.0,
|
||||
"countLong": 0
|
||||
},
|
||||
"errorCount": 0,
|
||||
"standardDeviationDuration": 0.0,
|
||||
"countsEnabled": true,
|
||||
"statsEnabled": true,
|
||||
"loggingEnabled": false,
|
||||
"handleCount": 0,
|
||||
"meanDuration": 0.0,
|
||||
"maxDuration": 0.0,
|
||||
"minDuration": 0.0,
|
||||
"activeCount": 0
|
||||
},
|
||||
"componentType": "logging-channel-adapter",
|
||||
"output": null,
|
||||
"input": "errorChannel"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"from": 2,
|
||||
"to": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
----
|
||||
|
||||
As you can see, the graph consists of three top-level elements.
|
||||
|
||||
The `contentDescriptor` graph element is pretty straightforward and contains general information about the application providing the data.
|
||||
The `name` can be customized on the `IntegrationGraphServer` bean or via `spring.application.name` application context environment property.
|
||||
Other properties are provided by the framework and allows you to 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`.
|
||||
The information from this element can be used by a visualizing 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.
|
||||
|
||||
The `nodes` graph element is perhaps the most interesting because its elements contain not only the runtime components with their `componentType` s and `name` s, but can also optionally contain metrics exposed by the component.
|
||||
To enable the metrics, add an `@EnableIntegrationManagement` to some `@Configuration` class or add an `<int:management/>` element to your XML configuration.
|
||||
You can control exactly which components in the framework collect statistics.
|
||||
See <<metrics-management>> for complete information.
|
||||
See the `stats` attribute from the `_org.springframework.integration.errorLogger` component in the JSON example above.
|
||||
The `nullChannel` and `errorChannel` don't provide statistics information in this case, because the configuration for this example was:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
@EnableIntegrationManagement(statsEnabled = "_org.springframework.integration.errorLogger.handler",
|
||||
countsEnabled = "!*",
|
||||
defaultLoggingEnabled = "false")
|
||||
public class ManagementConfiguration {
|
||||
|
||||
@Bean
|
||||
public IntegrationGraphServer integrationGraphServer() {
|
||||
return new IntegrationGraphServer();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
The `nodeId` represents a unique incremental identifier to 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 paragraph for more information.
|
||||
|
||||
==== 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 send messages from the source data periodically.
|
||||
Other components might be middleware request-reply components, e.g. `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 (e.g. `ApplicationEventListeningMessageProducer`) simply wraps some source protocol listening logic and sends messages to the `outputChannel`.
|
||||
|
||||
Within the graph, Spring Integration components are represented using the `IntegrationNode` class hierarchy, which you can find in the `o.s.i.support.management.graph` package.
|
||||
For example the `ErrorCapableDiscardingMessageHandlerNode` could be used for the `AggregatingMessageHandler` (because it has a `discardChannel` option) and can produce errors when consuming from a `PollableChannel` using a `PollingConsumer`.
|
||||
Another sample is `CompositeMessageHandlerNode` - for a `MessageHandlerChain` when subscribed to a `SubscribableChannel`, using an `EventDrivenConsumer`.
|
||||
|
||||
This `IntegrationNode` hierarchy can be used for parsing the graph model on the client side, as well as for the understanding the general Spring Integration runtime behavior.
|
||||
See also <<programming-tips>> for more information.
|
||||
|
||||
=== Integration Graph Controller
|
||||
|
||||
If your application is WEB-based (or built on top of Spring Boot using an embedded web container) and the Spring Integration HTTP module (see <<http>>) is present on the classpath, you can use a `IntegrationGraphController` to expose the `IntegrationGraphServer` functionality as a REST service.
|
||||
For this purpose, the `@EnableIntegrationGraphController` `@Configuration` class annotation and the `<int-http:graph-controller/>` XML element, are available in the HTTP module.
|
||||
Together with the `@EnableWebMvc` annotation (or `<mvc:annotation-driven/>` for xml definitions), this configuration registers an `IntegrationGraphController` `@RestController` where its `@RequestMapping.path` can be configured on the `@EnableIntegrationGraphController` annotation or `<int-http:graph-controller/>` element.
|
||||
The default path is `/integration`.
|
||||
|
||||
The `IntegrationGraphController` `@RestController` provides these services:
|
||||
|
||||
- `@GetMapping(name = "getGraph")` - to retrieve the state of the Spring Integration components since the last `IntegrationGraphServer` refresh.
|
||||
The `o.s.i.support.management.graph.Graph` is returned as a `@ResponseBody` of the REST service;
|
||||
- `@GetMapping(path = "/refresh", name = "refreshGraph")` - to refresh the current `Graph` for the actual runtime state and return it as a REST response.
|
||||
It is not necessaery to refresh the graph for metrics, they are provided in real-time when the graph is retrieved.
|
||||
Refresh can be called if the application context has been modified since the graph was last retrieved and the graph is completely rebuilt.
|
||||
|
||||
Any Security and Cross Origin restrictions for the `IntegrationGraphController` can be achieved with the standard configuration options and components provided by Spring Security and Spring MVC projects.
|
||||
The simple example of that may be:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<mvc:annotation-driven />
|
||||
|
||||
<mvc:cors>
|
||||
<mvc:mapping path="/myIntegration/**"
|
||||
allowed-origins="http://localhost:9090"
|
||||
allowed-methods="GET" />
|
||||
</mvc:cors>
|
||||
|
||||
<security:http>
|
||||
<security:intercept-url pattern="/myIntegration/**" access="ROLE_ADMIN" />
|
||||
</security:http>
|
||||
|
||||
|
||||
<int-http:graph-controller path="/myIntegration" />
|
||||
----
|
||||
|
||||
and the Java & Annotation Configuration variant is:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@EnableWebSecurity
|
||||
@EnableIntegration
|
||||
@EnableIntegrationGraphController(path = "/testIntegration")
|
||||
public class IntegrationConfiguration extends WebSecurityConfigurerAdapter
|
||||
implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/testIntegration/**").hasRole("ADMIN")
|
||||
// ...
|
||||
.formLogin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/testIntegration/**")
|
||||
.allowedOrigins("http://localhost:9090")
|
||||
.allowedMethods(HttpMethod.GET.name());
|
||||
}
|
||||
|
||||
//...
|
||||
|
||||
}
|
||||
----
|
||||
@@ -791,6 +791,12 @@ If further customization is required you can also configure a `DefaultHttpHeader
|
||||
|
||||
Of course, you can even implement the HeaderMapper strategy interface directly and provide a reference to that if you need to do something other than what the `DefaultHttpHeaderMapper` supports.
|
||||
|
||||
[[int-graph-controller]]
|
||||
=== Integration Graph Controller
|
||||
|
||||
Starting with _version 4.3_, the HTTP module provides an `@EnableIntegrationGraphController` `@Configuration` class annotation and `<int-http:graph-controller/>` XML element to expose the `IntegrationGraphServer` as a REST service.
|
||||
See <<integration-graph>> for more information.
|
||||
|
||||
[[http-samples]]
|
||||
=== HTTP Samples
|
||||
|
||||
|
||||
@@ -15,4 +15,6 @@ include::./meta-data-store.adoc[]
|
||||
include::./control-bus.adoc[]
|
||||
|
||||
include::./shutdown.adoc[]
|
||||
|
||||
include::./graph.adoc[]
|
||||
// BE SURE TO PRECEDE ALL include:: with a blank line - see https://github.com/asciidoctor/asciidoctor/issues/1297
|
||||
|
||||
@@ -38,6 +38,11 @@ See <<ftp-streaming>> and <<sftp-streaming>> for more information.
|
||||
A new `StreamTransformer` is provided to transform an `InputStream` payload to either a `byte[]` or `String`.
|
||||
See <<stream-transformer>> for more information.
|
||||
|
||||
==== Integration Graph
|
||||
|
||||
A new `IntegrationGraphServer` together with the `IntegrationGraphController` REST service are provided to expose the runtime model of a Spring Integration application as a graph.
|
||||
See <<integration-graph>> for more information.
|
||||
|
||||
[[x4.3-general]]
|
||||
=== General Changes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user