Some miscellaneous docs related fixed
This commit is contained in:
@@ -40,7 +40,7 @@ ext {
|
||||
linkScmUrl = 'https://github.com/spring-projects/spring-integration'
|
||||
linkScmConnection = 'scm:git:git://github.com/spring-projects/spring-integration.git'
|
||||
linkScmDevConnection = 'scm:git:ssh://git@github.com:spring-projects/spring-integration.git'
|
||||
docResourcesVersion = '0.2.3'
|
||||
docResourcesVersion = '0.2.4'
|
||||
|
||||
modifiedFiles =
|
||||
files(grgit.status().unstaged.modified).filter{ f -> f.name.endsWith('.java') || f.name.endsWith('.kt') }
|
||||
|
||||
@@ -28,7 +28,7 @@ publishing {
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'abilan'
|
||||
id = 'artembilan'
|
||||
name = 'Artem Bilan'
|
||||
email = 'abilan@vmware.com'
|
||||
roles = ["project lead"]
|
||||
|
||||
@@ -134,27 +134,27 @@ To accomplish this, you can use a messaging gateway by including a <gateway> ele
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:chain id="main-chain" input-channel="in" output-channel="out">
|
||||
<int:chain id="main-chain" input-channel="in" output-channel="out">
|
||||
<int:header-enricher>
|
||||
<int:header name="name" value="Many" />
|
||||
</int:header-enricher>
|
||||
<int:service-activator>
|
||||
<bean class="org.foo.SampleService" />
|
||||
</int:service-activator>
|
||||
<int:gateway request-channel="inputA"/>
|
||||
<int:gateway request-channel="inputA"/>
|
||||
</int:chain>
|
||||
|
||||
<int:chain id="nested-chain-a" input-channel="inputA">
|
||||
<int:chain id="nested-chain-a" input-channel="inputA">
|
||||
<int:header-enricher>
|
||||
<int:header name="name" value="Moe" />
|
||||
</int:header-enricher>
|
||||
<int:gateway request-channel="inputB"/>
|
||||
<int:gateway request-channel="inputB"/>
|
||||
<int:service-activator>
|
||||
<bean class="org.foo.SampleService" />
|
||||
</int:service-activator>
|
||||
</int:chain>
|
||||
|
||||
<int:chain id="nested-chain-b" input-channel="inputB">
|
||||
<int:chain id="nested-chain-b" input-channel="inputB">
|
||||
<int:header-enricher>
|
||||
<int:header name="name" value="Jack" />
|
||||
</int:header-enricher>
|
||||
|
||||
@@ -156,7 +156,7 @@ Later, we show how each of these channels can be configured.
|
||||
The `DirectChannel` internally delegates to a message dispatcher to invoke its subscribed message handlers, and that dispatcher can have a load-balancing strategy exposed by `load-balancer` or `load-balancer-ref` attributes (mutually exclusive).
|
||||
The load balancing strategy is used by the message dispatcher to help determine how messages are distributed amongst message handlers when multiple message handlers subscribe to the same channel.
|
||||
As a convenience, the `load-balancer` attribute exposes an enumeration of values pointing to pre-existing implementations of `LoadBalancingStrategy`.
|
||||
`round-robin` (load-balances across the handlers in rotation) and `none` (for the cases where one wants to explicitly disable load balancing) are the only available values.
|
||||
A `round-robin` (load-balances across the handlers in rotation) and `none` (for the cases where one wants to explicitly disable load balancing) are the only available values.
|
||||
Other strategy implementations may be added in future versions.
|
||||
However, since version 3.0, you can provide your own implementation of the `LoadBalancingStrategy` and inject it by using the `load-balancer-ref` attribute, which should point to a bean that implements `LoadBalancingStrategy`, as the following example shows:
|
||||
|
||||
@@ -999,9 +999,9 @@ For example, channel 'inputChannel' could have individual interceptors configure
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:channel id="inputChannel">
|
||||
<int:channel id="inputChannel">
|
||||
<int:interceptors>
|
||||
<int:wire-tap channel="logger"/>
|
||||
<int:wire-tap channel="logger"/>
|
||||
</int:interceptors>
|
||||
</int:channel>
|
||||
----
|
||||
|
||||
@@ -710,11 +710,11 @@ public String doSomething(Object o);
|
||||
----
|
||||
====
|
||||
|
||||
The input parameter is a message payload.
|
||||
If the parameter type is not compatible with a message payload, an attempt is made to convert it by using a conversion service provided by Spring 3.0.
|
||||
The input parameter is a message payload.
|
||||
If the parameter type is not compatible with a message payload, an attempt is made to convert it by using a conversion service provided by Spring 3.0.
|
||||
The return value is incorporated as a payload of the returned message.
|
||||
|
||||
The following example shows a single un-annotated parameter (object or primitive)that is not a `Map` or a `Properties` with a `Message` return type:
|
||||
The following example shows a single un-annotated parameter (object or primitive)that is not a `Map` or a `Properties` with a `Message` return type:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
@@ -723,8 +723,8 @@ public Message doSomething(Object o);
|
||||
----
|
||||
====
|
||||
|
||||
The input parameter is a message payload.
|
||||
If the parameter type is not compatible with a message payload, an attempt is made to convert it by using a conversion service provided by Spring 3.0.
|
||||
The input parameter is a message payload.
|
||||
If the parameter type is not compatible with a message payload, an attempt is made to convert it by using a conversion service provided by Spring 3.0.
|
||||
The return value is a newly constructed message that is sent to the next destination.
|
||||
|
||||
The followig example shows a single parameter that is a message (or one of its subclasses) with an arbitrary object or primitive return type:
|
||||
@@ -732,11 +732,11 @@ The followig example shows a single parameter that is a message (or one of its s
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public int doSomething(Message msg);
|
||||
public int doSomething(Message msg);
|
||||
----
|
||||
====
|
||||
|
||||
The input parameter is itself a `Message`.
|
||||
The input parameter is itself a `Message`.
|
||||
The return value becomes a payload of the `Message` that is sent to the next destination.
|
||||
|
||||
The following example shows a single parameter that is a `Message` (or one of its subclasses) with a `Message` (or one of its subclasses) as the return type:
|
||||
@@ -744,11 +744,11 @@ The following example shows a single parameter that is a `Message` (or one of it
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public Message doSomething(Message msg);
|
||||
public Message doSomething(Message msg);
|
||||
----
|
||||
====
|
||||
|
||||
The input parameter is itself a `Message`.
|
||||
The input parameter is itself a `Message`.
|
||||
The return value is a newly constructed `Message` that is sent to the next destination.
|
||||
|
||||
The following example shows a single parameter of type `Map` or `Properties` with a `Message` as the return type:
|
||||
@@ -775,7 +775,7 @@ public Message doSomething(Map h, <T> t);
|
||||
====
|
||||
|
||||
This combination contains two input parameters where one of them is of type `Map`.
|
||||
The non-`Map` parameters (regardless of the order) are mapped to a `Message` payload and the `Map` or `Properties` (regardless of the order) is mapped to message headers, giving you a nice POJO way of interacting with `Message` structure.
|
||||
The non-`Map` parameters (regardless of the order) are mapped to a `Message` payload and the `Map` or `Properties` (regardless of the order) is mapped to message headers, giving you a nice POJO way of interacting with `Message` structure.
|
||||
|
||||
The following example shows no parameters (regardless of the return):
|
||||
|
||||
@@ -808,7 +808,7 @@ The following example shows how to explicitly map a method to a header:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
public String doSomething(@Payload String s, @Header("someheader") String b)
|
||||
public String doSomething(@Payload String s, @Header("someheader") String b)
|
||||
----
|
||||
|
||||
As you can see later on, without an annotation this signature would result in an ambiguous condition.
|
||||
@@ -819,11 +819,11 @@ The following example is nearly identical to the preceding example:
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public String doSomething(@Payload String s, @RequestParam("something") String b)
|
||||
public String doSomething(@Payload String s, @RequestParam("something") String b)
|
||||
----
|
||||
====
|
||||
|
||||
`@RequestMapping` or any other non-Spring Integration mapping annotation is irrelevant and is therefore ignored, leaving the second parameter unmapped.
|
||||
`@RequestMapping` or any other non-Spring Integration mapping annotation is irrelevant and is therefore ignored, leaving the second parameter unmapped.
|
||||
Although the second parameter could easily be mapped to a payload, there can only be one payload.
|
||||
Therefore, the annotations keep this method from being ambiguous.
|
||||
|
||||
@@ -832,7 +832,7 @@ The following example shows another similar method that would be ambiguous were
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
public String foo(String s, @Header("foo") String b)
|
||||
public String foo(String s, @Header("foo") String b)
|
||||
----
|
||||
====
|
||||
|
||||
@@ -916,7 +916,7 @@ public class Something {
|
||||
|
||||
(Whether the methods have the same name or different names makes no difference).
|
||||
The `Message` could be mapped to either method.
|
||||
The first method would be invoked when the message payload could be mapped to `str` and the message headers could be mapped to `m`.
|
||||
The first method would be invoked when the message payload could be mapped to `str` and the message headers could be mapped to `m`.
|
||||
The second method could also be a candidate by mapping only the message headers to `m`.
|
||||
To make matters worse, both methods have the same name.
|
||||
At first, that might look ambiguous because of the following configuration:
|
||||
@@ -924,8 +924,8 @@ At first, that might look ambiguous because of the following configuration:
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:service-activator input-channel="input" output-channel="output" method="doSomething">
|
||||
<bean class="org.things.Something"/>
|
||||
<int:service-activator input-channel="input" output-channel="output" method="doSomething">
|
||||
<bean class="org.things.Something"/>
|
||||
</int:service-activator>
|
||||
----
|
||||
====
|
||||
@@ -967,8 +967,8 @@ The following example shows how to use the `method` attribute to dictate the map
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<int:service-activator input-channel="input" output-channel="output" method="doSomethingElse">
|
||||
<bean class="org.bar.Foo"/>
|
||||
<int:service-activator input-channel="input" output-channel="output" method="doSomethingElse">
|
||||
<bean class="org.bar.Foo"/>
|
||||
</int:service-activator>
|
||||
----
|
||||
Because the configuration explicitly maps the `doSomethingElse` method, we have eliminated the ambiguity.
|
||||
|
||||
@@ -355,7 +355,7 @@ For more information, see <<./transactions.adoc#transaction-poller,Poller Transa
|
||||
===== AOP Advice chains
|
||||
|
||||
Since Spring transaction support depends on the proxy mechanism with `TransactionInterceptor` (AOP Advice) handling transactional behavior of the message flow initiated by the poller, you must sometimes provide extra advices to handle other cross cutting behavior associated with the poller.
|
||||
For that, the `poller` defines an `advice-chain` element that lets you add more advices in a class that implements the `MethodInterceptor` interface.
|
||||
For that, the `poller` defines an `advice-chain` element that lets you add more advices in a class that implements the `MethodInterceptor` interface.
|
||||
The following example shows how to define an `advice-chain` for a `poller`:
|
||||
|
||||
====
|
||||
@@ -413,7 +413,7 @@ As mentioned earlier in the <<endpoint-pollingconsumer,background section for po
|
||||
With a long `receive-timeout` and a short `interval-trigger`, you can ensure a very timely reaction to arriving messages even on a polled message source.
|
||||
Note that this applies only to sources that have a blocking wait call with a timeout.
|
||||
For example, the file poller does not block.
|
||||
Each receive() call returns immediately and either contains new files or not.
|
||||
Each `receive()` call returns immediately and either contains new files or not.
|
||||
Therefore, even if a poller contains a long `receive-timeout`, that value would never be used in such a scenario.
|
||||
On the other hand, when using Spring Integration's own queue-based channels, the timeout value does have a chance to participate.
|
||||
The following example shows how a polling consumer can receive messages nearly instantaneously:
|
||||
@@ -459,8 +459,8 @@ It is not possible to force a trigger to fire before its currently configured ne
|
||||
[[payload-type-conversion]]
|
||||
==== Payload Type Conversion
|
||||
|
||||
Throughout this reference manual, you can also see specific configuration and implementation examples of various endpoints that accept a message or any arbitrary `Object` as an input parameter.
|
||||
In the case of an `Object`, such a parameter is mapped to a message payload or part of the payload or header (when using the Spring Expression Language).
|
||||
Throughout this reference manual, you can also see specific configuration and implementation examples of various endpoints that accept a message or any arbitrary `Object` as an input parameter.
|
||||
In the case of an `Object`, such a parameter is mapped to a message payload or part of the payload or header (when using the Spring Expression Language).
|
||||
However, the type of input parameter of the endpoint method sometimes does not match the type of the payload or its part.
|
||||
In this scenario, we need to perform type conversion.
|
||||
Spring Integration provides a convenient way for registering type converters (by using the Spring `ConversionService`) within its own instance of a conversion service bean named `integrationConversionService`.
|
||||
@@ -595,10 +595,10 @@ In this case, only the regular class-to-class conversion mentioned above in the
|
||||
==== Asynchronous Polling
|
||||
|
||||
If you want the polling to be asynchronous, a poller can optionally specify a `task-executor` attribute that points to an existing instance of any `TaskExecutor` bean (Spring 3.0 provides a convenient namespace configuration through the `task` namespace).
|
||||
However, there are certain things you must understand when configuring a poller with a `TaskExecutor`.
|
||||
However, there are certain things you must understand when configuring a poller with a `TaskExecutor`.
|
||||
|
||||
The problem is that there are two configurations in place, the poller and the `TaskExecutor`.
|
||||
They must be in tune with each other.
|
||||
They must be in tune with each other.
|
||||
Otherwise, you might end up creating an artificial memory leak.
|
||||
|
||||
Consider the following configuration:
|
||||
@@ -611,7 +611,7 @@ Consider the following configuration:
|
||||
</int:channel>
|
||||
|
||||
<int:service-activator input-channel="publishChannel" ref="myService">
|
||||
<int:poller receive-timeout="5000" task-executor="taskExecutor" fixed-rate="50" />
|
||||
<int:poller receive-timeout="5000" task-executor="taskExecutor" fixed-rate="50" />
|
||||
</int:service-activator>
|
||||
|
||||
<task:executor id="taskExecutor" pool-size="20" />
|
||||
|
||||
@@ -38,7 +38,7 @@ If the event's source is not a `Message` instance and no `payloadExpression` has
|
||||
Starting with version 4.2, the `ApplicationEventListeningMessageProducer` implements `GenericApplicationListener` and can be configured to accept not only `ApplicationEvent` types but any type for treating payload events (which are also supported since Spring Framework 4.2).
|
||||
When the accepted event is an instance of `PayloadApplicationEvent`, its `payload` is used for the message to send.
|
||||
|
||||
For convenience, namespace support is provided to configure an `ApplicationEventListeningMessageProducer` with the `inbound-channel-adapter` element, as the following example shows:
|
||||
For convenience, namespace support is provided to configure an `ApplicationEventListeningMessageProducer` with the `inbound-channel-adapter` element, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
@@ -106,7 +106,7 @@ public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer events
|
||||
To send Spring `ApplicationEvents`, create an instance of the `ApplicationEventPublishingMessageHandler` and register it within an endpoint.
|
||||
This implementation of the `MessageHandler` interface also implements Spring's `ApplicationEventPublisherAware` interface and consequently acts as a bridge between Spring Integration messages and `ApplicationEvents`.
|
||||
|
||||
For convenience, namespace support is provided to configure an `ApplicationEventPublishingMessageHandler` with the `outbound-channel-adapter` element, as the following example shows:
|
||||
For convenience, namespace support is provided to configure an `ApplicationEventPublishingMessageHandler` with the `outbound-channel-adapter` element, as the following example shows:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
|
||||
@@ -457,14 +457,14 @@ This means that there might be a chance that a message that was initiated by a g
|
||||
Some service activator method might result in an exception, thus providing no reply (as we do not generate null messages).
|
||||
In other words, multiple scenarios can cause a reply message to never come.
|
||||
That is perfectly natural in messaging systems.
|
||||
However, think about the implication on the gateway method. The gateway's method input arguments were incorporated into a message and sent downstream.
|
||||
However, think about the implication on the gateway method. The gateway's method input arguments were incorporated into a message and sent downstream.
|
||||
The reply message would be converted to a return value of the gateway's method.
|
||||
So you might want to ensure that, for each gateway call, there is always a reply message.
|
||||
Otherwise, your gateway method might never return and hang indefinitely.
|
||||
One way to handle this situation is by using an asynchronous gateway (explained later in this section).
|
||||
Another way of handling it is to explicitly set the `reply-timeout` attribute.
|
||||
That way, the gateway does not hang any longer than the time specified by the `reply-timeout` and returns 'null' if that timeout does elapse.
|
||||
Finally, you might want to consider setting downstream flags, such as 'requires-reply', on a service-activator or 'throw-exceptions-on-rejection' on a filter. These options are discussed in more detail in the final section of this chapter.
|
||||
Finally, you might want to consider setting downstream flags, such as 'requires-reply', on a service-activator or 'throw-exceptions-on-rejection' on a filter. These options are discussed in more detail in the final section of this chapter.
|
||||
|
||||
NOTE: If the downstream flow returns an `ErrorMessage`, its `payload` (a `Throwable`) is treated as a regular downstream error.
|
||||
If there is an `error-channel` configured, it is sent to the error flow.
|
||||
@@ -520,7 +520,7 @@ When configuring with XML, the timeout attributes can be a long value or a SpEL
|
||||
As a pattern, the messaging gateway offers a nice way to hide messaging-specific code while still exposing the full capabilities of the messaging system.
|
||||
As <<gateway-proxy,described earlier>>, the `GatewayProxyFactoryBean` provides a convenient way to expose a proxy over a service-interface giving you POJO-based access to a messaging system (based on objects in your own domain, primitives/Strings, or other objects).
|
||||
However, when a gateway is exposed through simple POJO methods that return values, it implies that, for each request message (generated when the method is invoked), there must be a reply message (generated when the method has returned).
|
||||
Since messaging systems are naturally asynchronous, you may not always be able to guarantee the contract where "`for each request, there will always be be a reply`". Spring Integration 2.0 introduced support for an asynchronous gateway, which offers a convenient way to initiate flows when you may not know if a reply is expected or how long it takes for replies to arrive.
|
||||
Since messaging systems are naturally asynchronous, you may not always be able to guarantee the contract where "`for each request, there will always be be a reply`". Spring Integration 2.0 introduced support for an asynchronous gateway, which offers a convenient way to initiate flows when you may not know if a reply is expected or how long it takes for replies to arrive.
|
||||
|
||||
To handle these types of scenarios, Spring Integration uses `java.util.concurrent.Future` instances to support an asynchronous gateway.
|
||||
|
||||
@@ -528,7 +528,7 @@ From the XML configuration, nothing changes, and you still define asynchronous g
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<int:gateway id="mathService"
|
||||
<int:gateway id="mathService"
|
||||
service-interface="org.springframework.integration.sample.gateway.futures.MathServiceGateway"
|
||||
default-request-channel="requestChannel"/>
|
||||
----
|
||||
@@ -558,7 +558,7 @@ The following example shows how to use a `Future` that returns from an asynchron
|
||||
MathServiceGateway mathService = ac.getBean("mathService", MathServiceGateway.class);
|
||||
Future<Integer> result = mathService.multiplyByTwo(number);
|
||||
// do something else here since the reply might take a moment
|
||||
int finalResult = result.get(1000, TimeUnit.SECONDS);
|
||||
int finalResult = result.get(1000, TimeUnit.SECONDS);
|
||||
----
|
||||
====
|
||||
|
||||
@@ -810,16 +810,16 @@ The rest of this section covers various scenarios and how to make the gateway be
|
||||
Certain attributes can be configured to make synchronous gateway behavior more predictable, but some of them might not always work as you might expect.
|
||||
One of them is `reply-timeout` (at the method level or `default-reply-timeout` at the gateway level).
|
||||
We examine the `reply-timeout` attribute to see how it can and cannot influence the behavior of the synchronous gateway in various scenarios.
|
||||
We examine a single-threaded scenario (all components downstream are connected through a direct channel) and multi-threaded scenarios (for example, somewhere downstream you may have a pollable or executor channel that breaks the single-thread boundary).
|
||||
We examine a single-threaded scenario (all components downstream are connected through a direct channel) and multi-threaded scenarios (for example, somewhere downstream you may have a pollable or executor channel that breaks the single-thread boundary).
|
||||
|
||||
[[long-running-process-downstream]]
|
||||
===== Long-running Process Downstream
|
||||
|
||||
Sync Gateway, single-threaded::
|
||||
If a component downstream is still running (perhaps because of an infinite loop or a slow service), setting a `reply-timeout` has no effect, and the gateway method call does not return until the downstream service exits (by returning or throwing an exception).
|
||||
Sync Gateway, multi-threaded::
|
||||
If a component downstream is still running (perhaps because of an infinite loop or a slow service) in a multi-threaded message flow, setting the `reply-timeout` has an effect by allowing gateway method invocation to return once the timeout has been reached, because the `GatewayProxyFactoryBean` polls on the reply channel, waiting for a message until the timeout expires.
|
||||
However, if the timeout has been reached before the actual reply was produced, it could result in a 'null' return from the gateway method.
|
||||
Sync Gateway, multi-threaded::
|
||||
If a component downstream is still running (perhaps because of an infinite loop or a slow service) in a multi-threaded message flow, setting the `reply-timeout` has an effect by allowing gateway method invocation to return once the timeout has been reached, because the `GatewayProxyFactoryBean` polls on the reply channel, waiting for a message until the timeout expires.
|
||||
However, if the timeout has been reached before the actual reply was produced, it could result in a 'null' return from the gateway method.
|
||||
You should understand that the reply message (if produced) is sent to a reply channel after the gateway method invocation might have returned, so you must be aware of that and design your flow with it in mind.
|
||||
|
||||
===== Downstream Component Returns 'null'
|
||||
|
||||
@@ -1035,24 +1035,24 @@ This section wraps up our coverage of Spring Integration's HTTP support with a f
|
||||
|
||||
This example shows how simple it is to send a multipart HTTP request with Spring's `RestTemplate` and receive it with a Spring Integration HTTP inbound adapter.
|
||||
We create a `MultiValueMap` and populate it with multipart data.
|
||||
The `RestTemplate` takes care of the rest (no pun intended) by converting it to a `MultipartHttpServletRequest`.
|
||||
The `RestTemplate` takes care of the rest (no pun intended) by converting it to a `MultipartHttpServletRequest`.
|
||||
This particular client sends a multipart HTTP Request that contains the name of the company and an image file (the company logo).
|
||||
The following listing shows the example:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
RestTemplate template = new RestTemplate();
|
||||
String uri = "http://localhost:8080/multipart-http/inboundAdapter.htm";
|
||||
Resource s2logo =
|
||||
new ClassPathResource("org/springframework/samples/multipart/spring09_logo.png");
|
||||
MultiValueMap map = new LinkedMultiValueMap();
|
||||
map.add("company", "SpringSource");
|
||||
RestTemplate template = new RestTemplate();
|
||||
String uri = "http://localhost:8080/multipart-http/inboundAdapter.htm";
|
||||
Resource s2logo =
|
||||
new ClassPathResource("org/springframework/samples/multipart/spring09_logo.png");
|
||||
MultiValueMap map = new LinkedMultiValueMap();
|
||||
map.add("company", "SpringSource");
|
||||
map.add("company-logo", s2logo);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType("multipart", "form-data"));
|
||||
HttpEntity request = new HttpEntity(map, headers);
|
||||
ResponseEntity<?> httpResponse = template.exchange(uri, HttpMethod.POST, request, null);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(new MediaType("multipart", "form-data"));
|
||||
HttpEntity request = new HttpEntity(map, headers);
|
||||
ResponseEntity<?> httpResponse = template.exchange(uri, HttpMethod.POST, request, null);
|
||||
----
|
||||
====
|
||||
|
||||
@@ -1079,7 +1079,7 @@ On the server side, we have the following configuration:
|
||||
----
|
||||
====
|
||||
|
||||
The 'httpInboundAdapter' receives the request and converts it to a `Message` with a payload that is a `LinkedMultiValueMap`.
|
||||
The 'httpInboundAdapter' receives the request and converts it to a `Message` with a payload that is a `LinkedMultiValueMap`.
|
||||
We then parse that in the 'multipartReceiver' service-activator, as the following example shows:
|
||||
|
||||
====
|
||||
|
||||
@@ -30,13 +30,13 @@ Consider the following configuration example:
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:gateway id="sampleGateway"
|
||||
<int:gateway id="sampleGateway"
|
||||
service-interface="org.springframework.integration.history.sample.SampleGateway"
|
||||
default-request-channel="bridgeInChannel"/>
|
||||
|
||||
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
|
||||
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
|
||||
<int:header-enricher>
|
||||
<int:header name="baz" value="baz"/>
|
||||
<int:header name="baz" value="baz"/>
|
||||
</int:header-enricher>
|
||||
</int:chain>
|
||||
----
|
||||
@@ -50,7 +50,7 @@ The preceding configuration produces a simple message history structure, with ou
|
||||
----
|
||||
|
||||
To get access to message history, you need only access the `MessageHistory` header.
|
||||
The folloiwng example shows how to do so:
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
|
||||
@@ -169,13 +169,13 @@ Now you can annotate any method with the `@Audit` annotation, as the following e
|
||||
----
|
||||
@Audit
|
||||
public String test() {
|
||||
return "Hello";
|
||||
return "Hello";
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
In the preceding example, every invocation of the `test()` method results in a message with a payload created from its return value.
|
||||
Each message is sent to the channel named `auditChannel`.
|
||||
Each message is sent to the channel named `auditChannel`.
|
||||
One of the benefits of this technique is that you can avoid the duplication of the same channel name across multiple annotations.
|
||||
You also can provide a level of indirection between your own, potentially domain-specific, annotations and those provided by the framework.
|
||||
|
||||
@@ -185,16 +185,16 @@ You can also annotate the class, which lets you apply the properties of this ann
|
||||
[source,java]
|
||||
----
|
||||
@Audit
|
||||
static class BankingOperationsImpl implements BankingOperations {
|
||||
static class BankingOperationsImpl implements BankingOperations {
|
||||
|
||||
public String debit(String amount) {
|
||||
. . .
|
||||
public String debit(String amount) {
|
||||
. . .
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String credit(String amount) {
|
||||
. . .
|
||||
}
|
||||
public String credit(String amount) {
|
||||
. . .
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
@@ -267,12 +267,12 @@ If you do not specify the `defaultChannel` (as the preceding example does not do
|
||||
|
||||
Publishing occurs in the same thread as your component's execution.
|
||||
So, by default, it is synchronous.
|
||||
This means that the entire message flow has to wait until the publisher's flow completes.
|
||||
This means that the entire message flow has to wait until the publisher's flow completes.
|
||||
However, developers often want the complete opposite: to use this message-publishing feature to initiate asynchronous flows.
|
||||
For example, you might host a service (HTTP, WS, and so on) which receives a remote request.
|
||||
You may want to send this request internally into a process that might take a while.
|
||||
However you may also want to reply to the user right away.
|
||||
So, instead of sending inbound requests for processing to the output channel (the conventional way), you can use 'output-channel' or a 'replyChannel' header to send a simple acknowledgment-like reply back to the caller while using the message-publisher feature to initiate a complex flow.
|
||||
So, instead of sending inbound requests for processing to the output channel (the conventional way), you can use 'output-channel' or a 'replyChannel' header to send a simple acknowledgment-like reply back to the caller while using the message-publisher feature to initiate a complex flow.
|
||||
|
||||
The service in the following example receives a complex payload (which needs to be sent further for processing), but it also needs to reply to the caller with a simple acknowledgment:
|
||||
|
||||
@@ -280,7 +280,7 @@ The service in the following example receives a complex payload (which needs to
|
||||
[source,java]
|
||||
----
|
||||
public String echo(Object complexPayload) {
|
||||
return "ACK";
|
||||
return "ACK";
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -293,7 +293,7 @@ The following example shows how to an asynchronous `publishing-interceptor`:
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:service-activator input-channel="inputChannel" output-channel="outputChannel" ref="sampleservice"/>
|
||||
<int:service-activator input-channel="inputChannel" output-channel="outputChannel" ref="sampleservice"/>
|
||||
|
||||
<bean id="sampleservice" class="test.SampleService"/>
|
||||
|
||||
@@ -341,7 +341,7 @@ Consider the following example:
|
||||
----
|
||||
====
|
||||
|
||||
The preceding example creates an inbound channel adapter that constructs a `Message`, with its payload being the result of the expression defined in the `expression` attribute.
|
||||
The preceding example creates an inbound channel adapter that constructs a `Message`, with its payload being the result of the expression defined in the `expression` attribute.
|
||||
Such messages are created and sent every time the delay specified by the `fixed-delay` attribute occurs.
|
||||
|
||||
The following example is similar to the preceding example, except that it uses the `fixed-rate` attribute:
|
||||
@@ -388,7 +388,7 @@ The following example shows how to insert additional headers into the message:
|
||||
|
||||
The additional message headers can take scalar values or the results of evaluating Spring expressions.
|
||||
|
||||
If you need to implement your own custom trigger, you can use the `trigger` attribute to provide a reference to any spring configured bean that implements the `org.springframework.scheduling.Trigger` interface.
|
||||
If you need to implement your own custom trigger, you can use the `trigger` attribute to provide a reference to any spring configured bean that implements the `org.springframework.scheduling.Trigger` interface.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
|
||||
@@ -15,13 +15,13 @@ This section details the compatible https://www.oracle.com/technetwork/java/java
|
||||
[[supported-java-versions]]
|
||||
=== Compatible Java Versions
|
||||
|
||||
For Spring Integration 5.2.x, the minimum compatible Java version is Java SE 8.
|
||||
For Spring Integration 5.4.x, the minimum compatible Java version is Java SE 8.
|
||||
Older versions of Java are not supported.
|
||||
|
||||
[[supported-spring-versions]]
|
||||
=== Compatible Versions of the Spring Framework
|
||||
|
||||
Spring Integration 5.2.x requires Spring Framework 5.2 or later.
|
||||
Spring Integration 5.4.x requires Spring Framework 5.3 or later.
|
||||
|
||||
[[code-conventions]]
|
||||
== Code Conventions
|
||||
@@ -67,6 +67,4 @@ Be aware, though, that SpringSource Tool Suite™ (STS) uses the same namespace
|
||||
[[guide-conventions]]
|
||||
== Conventions in This Guide
|
||||
|
||||
In some cases, to aid formatting when specifying long fully qualified class names, we shorten
|
||||
`org.springframework` to `o.s` and `org.springframework.integration` to `o.s.i`, such as with
|
||||
`o.s.i.transaction.TransactionSynchronizationFactory`.
|
||||
In some cases, to aid formatting when specifying long fully qualified class names, we shorten `org.springframework` to `o.s` and `org.springframework.integration` to `o.s.i`, such as with `o.s.i.transaction.TransactionSynchronizationFactory`.
|
||||
|
||||
@@ -898,7 +898,7 @@ public IntegrationFlow routerFlow() {
|
||||
Sometimes, the routing logic may be simple, and writing a separate class for it and configuring it as a bean may seem like overkill.
|
||||
As of Spring Integration 2.0, we offer an alternative that lets you use SpEL to implement simple computations that previously required a custom POJO router.
|
||||
|
||||
NOTE: For more information about the Spring Expression Language, see the https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[relevant chapter in the Spring Framework Reference Guide]:
|
||||
NOTE: For more information about the Spring Expression Language, see the https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[relevant chapter in the Spring Framework Reference Guide].
|
||||
|
||||
Generally, a SpEL expression is evaluated and its result is mapped to a channel, as the following example shows:
|
||||
|
||||
@@ -1034,7 +1034,7 @@ As another example, you may want to introduce more granularity to your message f
|
||||
Unfortunately, with static router configuration to accomplish either of those goals, you would have to bring down your entire application, change the configuration of the router (change routes), and bring the application back up.
|
||||
This is obviously not a solution anyone wants.
|
||||
|
||||
The https://www.enterpriseintegrationpatterns.com/DynamicRouter.html[dynamic router] pattern describes the mechanisms by which you can change or configure routers dynamically without bringing down the system or individual routers.
|
||||
The https://www.enterpriseintegrationpatterns.com/DynamicRouter.html[dynamic router] pattern describes the mechanisms by which you can change or configure routers dynamically without bringing down the system or individual routers.
|
||||
|
||||
Before we get into the specifics of how Spring Integration supports dynamic routing, we need to consider the typical flow of a router:
|
||||
|
||||
@@ -1091,7 +1091,7 @@ However, if you look at the alternate configuration of the `HeaderValueRouter` w
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:header-value-router input-channel="inputChannel" header-name="testHeader">
|
||||
<int:header-value-router input-channel="inputChannel" header-name="testHeader">
|
||||
----
|
||||
====
|
||||
|
||||
@@ -1099,8 +1099,8 @@ However, the configuration is still perfectly valid.
|
||||
So the natural question is what about the mapping in the second step?
|
||||
|
||||
The second step is now optional.
|
||||
If `mapping` is not defined, then the channel identifier value computed in the first step is automatically treated as the `channel name`, which is now resolved to the actual `MessageChannel`, as in the third step.
|
||||
What it also means is that the second step is one of the key steps to providing dynamic characteristics to the routers, since it introduces a process that lets you change the way channel identifier resolves to the channel name, thus influencing the process of determining the final instance of the `MessageChannel` from the initial channel identifier.
|
||||
If `mapping` is not defined, then the channel identifier value computed in the first step is automatically treated as the `channel name`, which is now resolved to the actual `MessageChannel`, as in the third step.
|
||||
What it also means is that the second step is one of the key steps to providing dynamic characteristics to the routers, since it introduces a process that lets you change the way channel identifier resolves to the channel name, thus influencing the process of determining the final instance of the `MessageChannel` from the initial channel identifier.
|
||||
|
||||
For example, in the preceding configuration, assume that the `testHeader` value is 'kermit', which is now a channel identifier (the first step).
|
||||
Since there is no mapping in this router, resolving this channel identifier to a channel name (the second step) is impossible and this channel identifier is now treated as the channel name.
|
||||
@@ -1120,7 +1120,7 @@ In fact, it applies to every other router, including expression-based routers, s
|
||||
Any router that is a subclass of the `AbstractMappingMessageRouter` (which includes most framework-defined routers) is a dynamic router, because the `channelMapping` is defined at the `AbstractMappingMessageRouter` level.
|
||||
That map's setter method is exposed as a public method along with the 'setChannelMapping' and 'removeChannelMapping' methods.
|
||||
These let you change, add, and remove router mappings at runtime, as long as you have a reference to the router itself.
|
||||
It also means that you could expose these same configuration options through JMX (see <<./jmx.adoc#jmx,JMX Support>>) or the Spring Integration control bus (see <<./control-bus.adoc#control-bus,Control Bus>>) functionality.
|
||||
It also means that you could expose these same configuration options through JMX (see <<./jmx.adoc#jmx,JMX Support>>) or the Spring Integration control bus (see <<./control-bus.adoc#control-bus,Control Bus>>) functionality.
|
||||
|
||||
IMPORTANT: Falling back to the channel key as the channel name is flexible and convenient.
|
||||
However, if you don't trust the message creator, a malicious actor (who has knowledge of the system) could create a message that is routed to an unexpected channel.
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
[[samples]]
|
||||
== Spring Integration Samples
|
||||
|
||||
As of Spring Integration 2.0, the Spring Integration distribution no longer includes the samples.
|
||||
As of Spring Integration 2.0, the Spring Integration distribution no longer includes the samples.
|
||||
Instead, we have switched to a much simpler collaborative model that should promote better community participation and, ideally, more contributions.
|
||||
Samples now have a dedicated Git repository and a dedicated JIRA Issue Tracking system.
|
||||
Samples now have a dedicated GitHub repository.
|
||||
Sample development also has its own lifecycle, which is not dependent on the lifecycle of the framework releases, although the repository is still tagged with each major release for compatibility reasons.
|
||||
|
||||
The great benefit to the community is that we can now add more samples and make them available to you right away without waiting for the next release.
|
||||
Having its own JIRA that is not tied to the the actual framework is also a great benefit.
|
||||
Having its own GitHub repository that is not tied to the the actual framework is also a great benefit.
|
||||
You now have a dedicated place to suggest samples as well as report issues with existing samples.
|
||||
You can also submit a sample to us as an attachment through JIRA or, better, through the collaborative model that Git promotes.
|
||||
You can also submit a sample to us as a Pull Request.
|
||||
If we believe your sample adds value, we would be more then glad to add it to the 'samples' repository, properly crediting you as the author.
|
||||
|
||||
[[samples-get]]
|
||||
=== Where to Get Samples
|
||||
|
||||
The Spring Integration Samples project is hosted on https://github.com/SpringSource/spring-integration-samples/[GitHub].
|
||||
You can find the repository at:
|
||||
|
||||
https://github.com/SpringSource/spring-integration-samples[https://github.com/SpringSource/spring-integration-samples]
|
||||
|
||||
The Spring Integration Samples project is hosted on https://github.com/spring-projects/spring-integration-samples/[GitHub].
|
||||
In order to check out or clone the samples, you must have a Git client installed on your system.
|
||||
There are several GUI-based products available for many platforms (such as https://eclipse.org/egit/[EGit] for the Eclipse IDE).
|
||||
A simple Google search can help you find them.
|
||||
@@ -32,7 +28,7 @@ To clone (check out) the Spring Integration samples repository by using the Git
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
$ git clone https://github.com/SpringSource/spring-integration-samples.git
|
||||
$ git clone https://github.com/spring-projects/spring-integration-samples.git
|
||||
----
|
||||
====
|
||||
|
||||
@@ -56,7 +52,7 @@ We greatly appreciate any effort toward improving the samples, including the sha
|
||||
==== How Can I Contribute My Own Samples?
|
||||
|
||||
Github is for social coding: if you want to submit your own code examples to the Spring Integration Samples project, we encourage contributions through https://help.github.com/en/articles/creating-a-pull-request/[pull requests] from https://help.github.com/en/articles/fork-a-repo[forks] of this repository.
|
||||
If you want to contribute code this way, please reference, if possible, a https://jira.springframework.org/browse/INTSAMPLES[JIRA ticket] that provides some details regarding your sample.
|
||||
If you want to contribute code this way, please reference, if possible, a https://github.com/spring-projects/spring-integration-samples/issues[GutHub issue] that provides some details regarding your sample.
|
||||
|
||||
[IMPORTANT]
|
||||
.Sign the contributor license agreement
|
||||
@@ -69,7 +65,7 @@ In order to read and sign the CLA, go to:
|
||||
https://support.springsource.com/spring_committer_signup
|
||||
|
||||
From the *Project* drop down, select *Spring Integration*.
|
||||
The Project Lead is Gary Russell.
|
||||
The Project Lead is Artem Bilan.
|
||||
=====
|
||||
|
||||
==== Code Contribution Process
|
||||
@@ -84,8 +80,8 @@ We gratefully look forward to your Spring Integration samples!
|
||||
|
||||
==== Sample Requests
|
||||
|
||||
As <<samples-how-can-i-contribute,mentioned earlier>>, the Spring Integration Samples project has a dedicated JIRA issue tracking system.
|
||||
To submit new sample requests, visit the JIRA Issue Tracking system at https://jira.springframework.org/browse/INTSAMPLES.
|
||||
As <<samples-how-can-i-contribute,mentioned earlier>>, the Spring Integration Samples project uses GitHub issue as bug tracking system.
|
||||
To submit new sample requests, visit https://github.com/spring-projects/spring-integration-samples/issues.
|
||||
|
||||
[[samples-structure]]
|
||||
=== Samples Structure
|
||||
@@ -108,12 +104,12 @@ For example, if you are looking for an answer on how to implement and wire a ser
|
||||
The bottom line is `samples/basic` is a good place to get started.
|
||||
|
||||
Intermediate (`samples/intermediate`)::
|
||||
This category targets developers who are already familiar with the Spring Integration framework (beyond getting started) but need some more guidance while resolving the more advanced technical problems they might encounter after switching to a messaging architecture.
|
||||
This category targets developers who are already familiar with the Spring Integration framework (beyond getting started) but need some more guidance while resolving the more advanced technical problems they might encounter after switching to a messaging architecture.
|
||||
For example, if you are looking for an answer on how to handle errors in various message exchange scenarios or how to properly configure the aggregator for a situation where some messages do not ever arrive for aggregation, or any other issue that goes beyond a basic implementation and configuration of a particular component and exposes "`what else`" types of problems, this is the right place to find these type of samples.
|
||||
|
||||
Advanced (`samples/advanced`)::
|
||||
This category targets developers who are very familiar with the Spring Integration framework but are looking to extend it to address a specific custom need by using Spring Integration's public API.
|
||||
For example, if you are looking for samples showing you how to implement a custom channel or consumer (event-based or polling-based) or you are trying to figure out the most appropriate way to implement a custom bean parser on top of the Spring Integration bean parser hierarchy (perhaps when implementing your own namespace and schema for a custom component), this is the right place to look.
|
||||
For example, if you are looking for samples showing you how to implement a custom channel or consumer (event-based or polling-based) or you are trying to figure out the most appropriate way to implement a custom bean parser on top of the Spring Integration bean parser hierarchy (perhaps when implementing your own namespace and schema for a custom component), this is the right place to look.
|
||||
Here you can also find samples that will help you with adapter development.
|
||||
Spring Integration comes with an extensive library of adapters to let you connect remote systems with the Spring Integration messaging framework.
|
||||
However, you might need to integrate with a system for which the core framework does not provide an adapter.
|
||||
@@ -141,8 +137,8 @@ In this section, you can find details on samples that we believe require special
|
||||
[[samples-loan-broker]]
|
||||
==== Loan Broker
|
||||
|
||||
This section covers the loan broker sample application that is included in the Spring Integration samples.
|
||||
This sample is inspired by one of the samples featured in Gregor Hohpe and Bobby Woolf's book, https://www.enterpriseintegrationpatterns.com/[_Enterprise Integration Patterns_].
|
||||
This section covers the loan broker sample application that is included in the Spring Integration samples.
|
||||
This sample is inspired by one of the samples featured in Gregor Hohpe and Bobby Woolf's book, https://www.enterpriseintegrationpatterns.com/[_Enterprise Integration Patterns_].
|
||||
|
||||
The following diagram shows the entire process:
|
||||
|
||||
@@ -313,8 +309,8 @@ Our goal is to make is so that integrating applications does not require changes
|
||||
[[samples-cafe]]
|
||||
==== The Cafe Sample
|
||||
|
||||
This section covers the cafe sample application that is included in the Spring Integration samples.
|
||||
This sample is inspired by another sample featured in Gregor Hohpe's https://www.enterpriseintegrationpatterns.com/ramblings.html[Ramblings].
|
||||
This section covers the cafe sample application that is included in the Spring Integration samples.
|
||||
This sample is inspired by another sample featured in Gregor Hohpe's https://www.enterpriseintegrationpatterns.com/ramblings.html[Ramblings].
|
||||
|
||||
The domain is that of a cafe, and the following diagram depicts the basic flow:
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ However, this section is relevant as well.
|
||||
[[scripting-config]]
|
||||
==== Script Configuration
|
||||
|
||||
Depending on the complexity of your integration requirements, scripts may be provided inline as CDATA in XML configuration or as a reference to a Spring resource that contains the script.
|
||||
To enable scripting support, Spring Integration defines a `ScriptExecutingMessageProcessor`, which binds the message payload to a variable named `payload` and the message headers to a `headers` variable, both accessible within the script execution context.
|
||||
Depending on the complexity of your integration requirements, scripts may be provided inline as CDATA in XML configuration or as a reference to a Spring resource that contains the script.
|
||||
To enable scripting support, Spring Integration defines a `ScriptExecutingMessageProcessor`, which binds the message payload to a variable named `payload` and the message headers to a `headers` variable, both accessible within the script execution context.
|
||||
All you need to do is write a script that uses these variables.
|
||||
The following pair of examples show sample configurations that create filters:
|
||||
|
||||
@@ -91,7 +91,7 @@ To do so, specify the `refresh-check-delay` attribute on the `script` element, a
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int-script:script location="..." refresh-check-delay="5000"/>
|
||||
<int-script:script location="..." refresh-check-delay="5000"/>
|
||||
----
|
||||
====
|
||||
|
||||
@@ -103,7 +103,7 @@ Consider the following example:
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int-script:script location="..." refresh-check-delay="0"/>
|
||||
<int-script:script location="..." refresh-check-delay="0"/>
|
||||
----
|
||||
====
|
||||
|
||||
@@ -115,7 +115,7 @@ The following example shows a script that never updates:
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int-script:script location="..." refresh-check-delay="-1"/>
|
||||
<int-script:script location="..." refresh-check-delay="-1"/>
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ In other words, these message flows depend on a third party process (such as som
|
||||
|
||||
* Message flows initiated by a daemon process: Example scenarios in this category include a Poller polling a message queue to initiate a new message flow with the polled message or a scheduler scheduling the process by creating a new message and initiating a message flow at a predefined time.
|
||||
|
||||
Clearly the gateway proxy, `MessageChannel.send(...)` and `MessagePublisher` all belong to the first category, and inbound adapters and gateways, scheduler, and poller belong to the second category.
|
||||
Clearly the gateway proxy, `MessageChannel.send(...)` and `MessagePublisher` all belong to the first category, and inbound adapters and gateways, scheduler, and poller belong to the second category.
|
||||
|
||||
So, how can you address transactional needs in various scenarios within each category, and is there a need for Spring Integration to provide something explicit with regard to transactions for a particular scenario?
|
||||
Or can you use Spring's transaction support instead?
|
||||
@@ -47,7 +47,7 @@ In other words, as a framework, we must expose hooks to Spring's transaction man
|
||||
However, since Spring Integration configuration is based on Spring configuration, we need not always expose these hooks, because Spring already exposes them .
|
||||
After all, every Spring Integration component is a Spring Bean.
|
||||
|
||||
With this goal in mind, we can again consider the two scenarios: messgae flows initiated by a user process and message flows initiated by a daemon.
|
||||
With this goal in mind, we can again consider the two scenarios: message flows initiated by a user process and message flows initiated by a daemon.
|
||||
|
||||
Message flows that are initiated by a user process and configured in a Spring application context are subject to the usual transactional configuration of such processes.
|
||||
Therefore they need not be explicitly configured by Spring Integration to support transactions.
|
||||
@@ -71,7 +71,7 @@ Spring Integration provides transactional support for pollers.
|
||||
Pollers are a special type of component because, within a poller task, we can call `receive()` against a resource that is itself transactional, thus including the `receive()` call in the the boundaries of the transaction, which lets it be rolled back in case of a task failure.
|
||||
If we were to add the same support for channels, the added transactions would affect all downstream components starting with the `send()` call.
|
||||
That provides a rather wide scope for transaction demarcation without any strong reason, especially when Spring already provides several ways to address the transactional needs of any component downstream.
|
||||
However the `receive()` method being included in a transaction boundary is the "`strong reason`" for pollers.
|
||||
However the `receive()` method being included in a transaction boundary is the "`strong reason`" for pollers.
|
||||
|
||||
Any time you configure a Poller, you can provide transactional configuration by using the `transactional` child element and its attributes,as the following example shows:
|
||||
|
||||
@@ -79,10 +79,10 @@ Any time you configure a Poller, you can provide transactional configuration by
|
||||
[source,xml]
|
||||
----
|
||||
<int:poller max-messages-per-poll="1" fixed-rate="1000">
|
||||
<transactional transaction-manager="txManager"
|
||||
<transactional transaction-manager="txManager"
|
||||
isolation="DEFAULT"
|
||||
propagation="REQUIRED"
|
||||
read-only="true"
|
||||
propagation="REQUIRED"
|
||||
read-only="true"
|
||||
timeout="1000"/>
|
||||
</poller>
|
||||
----
|
||||
@@ -110,7 +110,7 @@ The following example shows how to do so:
|
||||
<int:poller max-messages-per-poll="1" fixed-rate="10000">
|
||||
<advice-chain>
|
||||
<ref bean="txAdvice"/>
|
||||
<ref bean="someAotherAdviceBean" />
|
||||
<ref bean="someOtherAdviceBean" />
|
||||
<beans:bean class="foo.bar.SampleAdvice"/>
|
||||
</advice-chain>
|
||||
</poller>
|
||||
|
||||
@@ -122,7 +122,7 @@ For more sophistication (such as selection of the charset dynamically, at runtim
|
||||
====
|
||||
|
||||
If you need to serialize an `Object` to a byte array or deserialize a byte array back into an `Object`, Spring Integration provides symmetrical serialization transformers.
|
||||
These use standard Java serialization by default, but you can provide an implementation of Spring 3.0's serializer or seserializer strategies by using the `serializer` and `deserializer` attributes, respectively.
|
||||
These use standard Java serialization by default, but you can provide an implementation of Spring `Serializer` or `Deserializer` strategies by using the `serializer` and `deserializer` attributes, respectively.
|
||||
The following example shows to use Spring's serializer and deserializer:
|
||||
|
||||
====
|
||||
@@ -151,15 +151,15 @@ Consider the following example:
|
||||
[source,java]
|
||||
----
|
||||
public class Parent{
|
||||
private Child child;
|
||||
private String name;
|
||||
// setters and getters are omitted
|
||||
private Child child;
|
||||
private String name;
|
||||
// setters and getters are omitted
|
||||
}
|
||||
|
||||
public class Child{
|
||||
private String name;
|
||||
private List<String> nickNames;
|
||||
// setters and getters are omitted
|
||||
private String name;
|
||||
private List<String> nickNames;
|
||||
// setters and getters are omitted
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -181,15 +181,15 @@ For example, the preceding structure could be restored back to the following obj
|
||||
[source,java]
|
||||
----
|
||||
public class Father {
|
||||
private Kid child;
|
||||
private String name;
|
||||
// setters and getters are omitted
|
||||
private Kid child;
|
||||
private String name;
|
||||
// setters and getters are omitted
|
||||
}
|
||||
|
||||
public class Kid {
|
||||
private String name;
|
||||
private List<String> nickNames;
|
||||
// setters and getters are omitted
|
||||
private String name;
|
||||
private List<String> nickNames;
|
||||
// setters and getters are omitted
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -249,25 +249,25 @@ Spring Integration provides namespace support for Map-to-Object, as the followin
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<int:map-to-object-transformer input-channel="input"
|
||||
output-channel="output"
|
||||
type="org.something.Person"/>
|
||||
<int:map-to-object-transformer input-channel="input"
|
||||
output-channel="output"
|
||||
type="org.something.Person"/>
|
||||
----
|
||||
====
|
||||
|
||||
Alterately, you could use a `ref` attribute and a prototype-scoped bean, as the following example shows:
|
||||
[source,xml]
|
||||
----
|
||||
<int:map-to-object-transformer input-channel="inputA"
|
||||
output-channel="outputA"
|
||||
ref="person"/>
|
||||
<int:map-to-object-transformer input-channel="inputA"
|
||||
output-channel="outputA"
|
||||
ref="person"/>
|
||||
<bean id="person" class="org.something.Person" scope="prototype"/>
|
||||
|
||||
----
|
||||
|
||||
NOTE: The 'ref' and 'type' attributes are mutually exclusive.
|
||||
Also, if you use the 'ref' attribute, you must point to a 'prototype' scoped bean.
|
||||
Otherwise, a `BeanCreationException` is thrown.
|
||||
Otherwise, a `BeanCreationException` is thrown.
|
||||
|
||||
Starting with version 5.0, you can supply the `ObjectToMapTransformer` with a customized `JsonObjectMapper` -- for when you need special formats for dates or nulls for empty collections (and other uses).
|
||||
See <<json-transformers>> for more information about `JsonObjectMapper` implementations.
|
||||
|
||||
@@ -494,12 +494,12 @@ Spring Integration provides two convenient ways to accomplish this, as the follo
|
||||
----
|
||||
====
|
||||
|
||||
If message header names match one-to-one to parameter names, you can use the `xslt-param-headers` attribute.
|
||||
If message header names match one-to-one to parameter names, you can use the `xslt-param-headers` attribute.
|
||||
In it, you can use wildcards for simple pattern matching.
|
||||
It supports the following simple pattern styles: `xxx*`, `*xxx`, `*xxx*`, and `xxx*yyy`.
|
||||
|
||||
You can also configure individual XSLT parameters by using the `<xslt-param/>` element.
|
||||
On that element, you can set the `expression` attribute or the `value` attribute.
|
||||
On that element, you can set the `expression` attribute or the `value` attribute.
|
||||
The `expression` attribute should be any valid SpEL expression with the `Message` being the root object of the expression evaluation context.
|
||||
The `value` attribute (as with any `value` in Spring beans) lets you specify simple scalar values.
|
||||
You can also use property placeholders (such as `${some.value}`).
|
||||
|
||||
Reference in New Issue
Block a user