JIRA: https://jira.spring.io/browse/INT-4095
Limit the number of remote files fetched on each poll (when it is necessary to fetch files).
Polishing - PR Comments
Polishing - Decouple MaxFetchSize from Poller
Polishing - PR Comments
Schemas and Docs
More Polishing
* Polishing according PR comments
https://build.spring.io/browse/INT-SI43X-6/
Since Exponential Moving Average algorithm is fully based on the time in between events, it is very difficult to reach the stable tests.
All of them used to fail from time to time on the slow CI server.
Mark all Exponential Moving Average Tests with `@Ignore`.
The manual testing is required in case of some changes.
**Cherry-pick to 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4099
The `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` value has a typo
* Fix the typo in the `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` constant value
* Fix the same type in the (s)ftp.adoc
JIRA: https://jira.spring.io/browse/INT-4062
Only Enforce When an Executor is Provided
With `ExecutorChannel` and `PublishSubscribeChannel` (when an executor is provided),
any early subscription is lost because the dispatcher is replaced.
checkstyle
JIRA: https://jira.spring.io/browse/INT-4069
Finding annotations with AnnotatedElementUtils allows us to use
explicit annotation attribute overrides specified by the @AliasFor
annotation.
* Upgrade to the latest Reactor-2.5.0
* Fix all `Promise` and `Streams` mentioning to the `Mono` and `Flux`
* Add `ReactiveEndpoint.SubscribableChannelPublisherAdapter` to adapt `SubscribableChannel` into a `Publisher` for Reactive downstream
* Add `ReactiveMessageChannel` implementation based on the provided `Processor<?>` for internal dispatching logic.
Implement the `Publisher<?>` contract to allow downstream `Subscriber<?>`
* Add `ReactiveEndpoint` implementation to deal with the `ReactiveMessageChannel` through the Reactive Streams contract.
* Add appropriate `ReactiveEndpoint` building logic to the `ConsumerEndpointFactoryBean` and `AbstractMethodAnnotationPostProcessor`
* Rework Gateway to use `Publisher<?>` contract instead of `Promise` implementation.
JIRA: https://jira.spring.io/browse/INT-4078
Even if it doesn't hurt to `copyHeadersIfAbsent()`, when it just adds a new headers and doesn't override existing like sequence details,
it doesn't sound reasonable for `Resequencer` to modify the message before and after its resequence logic.
* Change `shouldCopyRequestHeaders()` to `false` for `ResequencingMessageHandler`
JIRA: https://jira.spring.io/browse/INT-4064
We configure `IdempotentReceiver` via `<int:idempotent-receiver>` component or `@IdempotentReceiver` annotation.
In case of regular Java config, e.g. direct `ConsumerEndpointFactoryBean` usage or Java DSL,
it isn't possible to configure `idempotentReceiverInterceptor` enough easy
* Introduce `if...else` logic into `ConsumerEndpointFactoryBean` to proxy `MessageHandler`,
if `adviceChain` contains an newly-introduced `HandleMessageAdvice`.
And do that independently if `MessageHandler` is `AbstractReplyProducingMessageHandler`
* Make `idempotentReceiverInterceptor extends HandleMessageAdvice`
* Skip `HandleMessageAdvice` in the `AbstractReplyProducingMessageHandler`
* Add advice applying logic into the `AbstractMethodAnnotationPostProcessor` as well
Introduce `HandleMessageAdvice` marker interceptor to cover the case when an `Advice` can be advices as well.
Remove unused `setAdviceChainIfPresent()` method in the `AbstractMethodAnnotationPostProcessor`
Document `HandleMessageAdvice`
Increase wait latch timeouts in the `LockRegistryLeaderInitiatorTests`
Doc Polishing
JIRA: https://jira.spring.io/browse/INT-4070
The `MessagingGatewaySupport.receive()` is fully based on the `this.messagingTemplate.receiveAndConvert(replyChannel, null);`
which really just extracts `payload` from the `Message` via default `MessageConverter`.
Therefore `@Gateway` code, which expects to poll exactly `Message<?>` from the flow, is invalid at runtime with `ClassCastException`
* Expose `MessagingGatewaySupport.messagingTemplate` property as `protected` to give access for inheritors and siblings
* In the `GatewayProxyFactoryBean` use `messagingTemplate` and `replyChannel` directly from the `MethodInvocationGateway`
to invoke raw `gateway.messagingTemplate.receive(replyChannel)` bypassing any conversion and to avoid breaking changes.
* Proof the solution with `GatewayProxyFactoryBean.testReceiveMessage()`
**Consider to cherry-pick (backport) down to 3.0.x**
Add `messagingGateway.convertReceiveMessage` global property to let revert to previous behavior
* Make `messagingGateway.convertReceiveMessage=true` by default
* Mock `BeanFactory` in the `GatewayProxyFactoryBeanTests.testReceiveMessage()`
to be sure that `messagingGateway.convertReceiveMessage=false` works as expected
* Add `testReceiveMessageConvert()` to demonstrate `ClassCastException`
Rebase and make `convertReceiveMessage` integration property as `false` by default
Introduce `MessagingGatewaySupport.receiveMessage()` and use it from the `GatewayProxyFactoryBean`
JIRA: https://jira.spring.io/browse/INT-4072
When `publishSubscribeChannel` is with `applySequence = true`, a `messageToSend` is overridden with `sequenceDetails` using `MessageBuilder`, therefore a new fresh `Message`.
In case of state propagation, e.g. `SecurityContextPropagationChannelInterceptor`, we just lost the state from the `ThreadStatePropagationChannelInterceptor.MessageWithThreadState` because of new `Message<?>`
* Add into `BroadcastingDispatcher` the logic to delegate `pushSequenceDetails` into `MessageWithThreadState` directly do not lose the `state`
* Make `ThreadStatePropagationChannelInterceptor` as `MessageBuilderFactory`-aware and use it to rebuild an `original` `Message<?>` in the `MessageWithThreadState` to populate `SequenceDetails`
**Cherry-pick to 4.2.x**
Provide an explicit order for `publishSubscribeChannel` subscribers
Fixes GH-1847 (https://github.com/spring-projects/spring-integration/issues/1847)
Fix mutation in the `ThreadStatePropagationChannelInterceptor`
Since `BroadcastingDispatcher` invokes `pushSequenceDetails` for each subscribed handler,
make `MessageWithThreadState` as immutable and return a new instance via `cloneWithSequenceDetails()` method with particular `sequenceDetails`.
Previous mutable solution ended up with the issue of concurrent modification.
* Introduce `CloneableMessage` abstraction to let any custom `Message` to return `MessageBuilder` with desired context.
* Introduce `DelegatingMessageBuilder` as an extension of the `MessageBuilder` to let custom `CloneableMessage` to return desired customization.
* Add into `MessageBuilder#fromMessage()` `if` for the `CloneableMessage`
* Add into `MutableMessageBuilder` a `warn` about `CloneableMessage`
* Revert changes in the `BroadcastingDispatcher` in favor of `CloneableMessage` in the `MessageBuilder`
* Redo `ThreadStatePropagationChannelInterceptor#MessageWithThreadState` logic to be based on the `CloneableMessage` and `DelegatingMessageBuilder` extension.
Introduce `MessageDecorator` contract
Remove `CloneableMessage` aspect and everything around
`MessageWithThreadState` is now `MessageDecorator` and `BroadcastingDispatcher` check if incoming `message` is `MessageDecorator` and performs its `decorateMessage` after `builder`
JIRA: https://jira.spring.io/browse/INT-4074
If the `@ServiceActivator` component is processed first the application will start.
However, if another component that relies on the channel creation goes first it'll fail as the bean for the channel does not exist.
* Add `name` setters for all channels in the `GatewayProxyFactoryBean` to allow late channel resolution in the target `MethodInvocationGateway`
* Change `MessagingGatewayRegistrar` to populate channel properties as names not bean references
**Cherry-pick to 4.2.x**
JIRA: https://jira.spring.io/browse/INT-4013
Previously we couldn't define a config as :
````xml
<int:channel-interceptor pattern="input*">
<ref bean="sampleInterceptor" />
</int:channel-interceptor>
````
* Fix `GlobalChannelInterceptorParser` to distinguish `BeanDefinitionParserDelegate.REF_ELEMENT` child elements
and extract an appropriate `BeanReference`
* Modify `GlobalChannelInterceptorTests-context.xml` to prove the fix and meet JIRA requirements
JIRA: https://jira.spring.io/browse/INT-4057
When general router `channelKey` returns just a `Class<?>` result, we end up with the
`unsupported return type for router [class java.lang.Class]` and forced to to call its `getName()` in the target application code before returning to router.
* Change the `AbstractMappingMessageRouter` logic to treat `Class<?>` as a special String-aware case, use its `getName()` and don't go to the `ConversionService`
* Increase receive timeout for replies in the `TcpInboundGatewayTests`
See https://build.spring.io/browse/INT-AT42SIO-199/
In some places we start `Cache` but doesn't close/destroy it in the end.
That sometimes causes conflicts with the already started GemFire from other tests or wrong state around `BeanFactoryLocator`
* Ensure `Cache` destroy in the end of each test
* In addition destroy `Region` as well to avoid unexpected race conditions, too
* Plus optimize some tests to start `Cache` and `Region` only once per test class, not for each test method
From here I can say that it even would be better to start `Cache`, and therefore whole GemFire, only once per entire Gemfire module test suite.
But that is fully different story.
Remove `forkEvery` from Gemfire module
Allow get a performance improvement for the build.
The `gradlew clean :spring-integration-gemfire:testAll` with existing state is like:
```
Total time: 3 mins 41.375 secs
```
With this fix and without `forkEvery`:
```
Total time: 1 mins 42.699 secs
```
So, 2 min saved time!
Plus fix timeouts in the `PayloadSerializingTransformerParserTests`
JIRA: https://jira.spring.io/browse/INT-1463
An existing `QueueChannel#getRemainingCapacity()` is based on the `BlockingQueue#getRemainingCapacity()` which is always `Integer.MAX_VALUE`
and doesn't reflect reality for provided `capacity`
* Fix `PriorityChannel` to return `upperBound.availablePermits()` for `getRemainingCapacity()`
* Add test for `PriorityChannel` on the matter
* Also increase `reply-timeout` for `<int-redis:queue-outbound-gateway>` in `RedisQueueGatewayIntegrationTests-context.xml` from 1 sec to 10 secs
JIRA: https://jira.spring.io/browse/INT-4058
If you hold the lock, you are the leader. This simple idea gets you
a long way if there is no "native" leader initiator. E.g. you
can use this with a RDBMS with JdbcLockRegistry.
Add some docs on leader election under "endpoints"
Make thread name for leader initiator unique
In case there are multiple instances in the same context we would
like to be able to spot them in the logs.
INT-4058: Polishing
* Code refactoring in the `LockRegistryLeaderInitiator`: SI use 120 line length
* Add `Assert.notNull()` for required properties
* Add `this.lock.unlock()` and `Thread.sleep(LockRegistryLeaderInitiator.this.busyWaitMillis)` into the `catch` block to let distributed elections to work.
Otherwise there is a big chance that we will acquire the lock and become a leader again just after `yield()`
* Change `LockContext.toString()` to use simple `String` concatenation which is optimized by compiler to the `StringBuilder`.
That let to have some better micro-performance compared with with extra `Formatter` object in case of `String.format()`
* Add `JdbcLockRegistryLeaderInitiatorTests`
* Fix `yield()` logic based on the `Future.cancel(true)`.
Since one `FutureTask.cancel(true)` makes it as `INTERRUPTED` any subsequent `yield()` does not make any effect, therefore our infinite selector loop isn't interrupted one more time.
* Reschedule the `LeaderSelector` in the `yield()` after cancel(true).
* Rework `catch` in the selector loop just to the `InterruptedException` and `return null;` to stop looping and let reschedule the selector.
* Add one more `onRevoked` logic into the `final` of the selector loop to notify that we have lost leadership during `stop()`
* Improve `JdbcLockRegistryLeaderInitiatorTests` to ensure that several `yield()` on the same initiator work well.
* Add `What's New` note.
JIRA: https://jira.spring.io/browse/INT-4054
Fixes GH-1833 (https://github.com/spring-projects/spring-integration/issues/1833)
The `DefaultCandidate` pulled requirement for the `slf4j` dependency via its `Logger` and `LoggerFactory` usage.
* Change `slf4j` to the standard Commons Logging
* Exclude `slf4j` transitive dependencies from `optional` direct dependencies like `reactor` and `json-path`
* Since they are `optional` it is safe to exclude their transitives to force our source code to be free from unexpected dependencies.
Anyway they don't appear in the target application as a SI transitives and end-user is forced to pull them manually to switch on the desired features.
If there is need in the `slf4j` for target application, it must be pulled manually as well.
**Cherry-pick to 4.2.x**
JIRA: https://jira.spring.io/browse/INT-4051
Previously we can process `@Publisher` annotations only with the `<int:annotation-config>` or with an explicit `@EnablePublisher("")`
* Fix `PublisherRegistrar` to relax from the fact if we have `@EnablePublisher` or not and register `PublisherAnnotationBeanPostProcessor` without `defaultChannelName`
JIRA: https://jira.spring.io/browse/INT-4045
Handle the situation when the first element of a container type (or map)
is null; set the generic type of the container to `Object`.
Also, clarify how the compatibility between the transformer and Spring AMQP
message converter is achieved.
JIRA: https://jira.spring.io/browse/INT-4043
The `ExecutorChannel` overrides `onInit()` but fails to call the super
which is where the message converter for datatype conversion is set up.
Also, when Jackson is not on the class path and there are no converters in the
context, the default integration conversion service is not registered.
The `DefaultDatatypeChannelMessageConverter` overwites its default conversion
service with this bean, unconditionally - setting it to null in this case.
Check for a null conversion service before replacing the default.
* Polishing according PR comments
JIRA: https://jira.spring.io/browse/INT-4038
General format for node name: bean.method#n
The #n is needed to disambiguate methods with the same name.
Polishing according PR comments
* Fix generic type for `Collections.unmodifiableMap` usage
* Change the gateway method logic in the `IntegrationGraphServer` to include the method signature in the node name to distinguish them as unique
* Move `MutableMessageBuilderFactoryTests` into the separate nested `mutable` package since `@IntegrationComponentScan` sees a new `@MessagingGateway` in the `IntegrationGraphServerTests`.
See https://jira.spring.io/browse/INT-4040
* Document the `@MessagingGateway` representation in the `graph.adoc`
The `RedisMessageGroupStoreTests.testMessageGroupUpdatedDateChangesWithEachAddedMessage()` can fail
sporadically because there is no guaranty the several calls to the `System.getCurrentTimeMillis()` return the same value.
* Fix `AbstractKeyValueMessageStore` to reuse `MessageGroup.timestamp` for the `lastModified` in case of a new group
https://build.spring.io/browse/INT-B43-199/
The `circuitBreakerTests()` relied on the enough short `Thread.sleep(100)`,
which may not be enough in the heavy-load environment like CI Server.
Therefor the time in between thread switching really can be much bigger than expected.
* Fix the test via timeout "emulation" using reflection to set the `lastFailure` somewhere in the past
to overcome `RequestHandlerCircuitBreakerAdvice.halfOpenAfter` barrier
JIRA: https://jira.spring.io/browse/INT-4021
Previously the `SimpleMessageStore` unconditionally followed with the super class options
and provided the `lazy-load` functionality by default.
* Since `persistent` and `lazy-load` logic does not make sense for the `in-memory` store, disable it in the `SimpleMessageStore`
* Fir `AggregatorTests` for better coverage.
* NOTE: The same message can't be persisted in the Persistent `MessageStore`. The store key is fully based on the `messageId`.
And also we provide the header which indicates that the messages has been stored before. See `JdbcMessageStore.addMessage()` for example:
```
if (message.getHeaders().containsKey(SAVED_KEY)) {
Message<T> saved = (Message<T>) getMessage(message.getHeaders().getId());
if (saved != null) {
if (saved.equals(message)) {
return message;
} // We need to save it under its own id
}
}
```
* Fix (S)FTP Streaming tests to use `AbstractPersistentAcceptOnceFileListFilter` instead of raw `AcceptOnceFileListFilter`,
which relies on the object identity, but neither `FtpFile`, nor `ChannelSftp.LsEntry` provides good `equals()` and `hashCode()` implementations.
* Make `StompIntegrationTests` as `DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD` because the sporadic failure on the Travis around wrong value from the queue isn't clear (yet).
Looks like some interim event is generated by the Websocket Container on the Tomcat.
JIRA: https://jira.spring.io/browse/INT-4020
The fix for `named` global `wire-tap`s (INT-2230) didn't covered testing for `unnamed`.
Therefore the fix unconditionally didn't picked up the issue that we used a wrong `BeanDefinition` to determine the current `id`
* Fix `WireTapParser` to use `wireTapBeanName` from the `resolveId()` when the `GlobalChannelInterceptorParser` invokes it.
* Add tests to demonstrate the issue and confirm the fix
**Cherry-pick to 4.2.x**
JIRA: https://jira.spring.io/browse/INT-4005
* The `<int:queue>` lets declare the `capacity` attribute together
with either `message-store` or `ref` attributes, which it is not
correct
* The `<int:queue>` lets declare the `capacity` attribute together
with either `message-store` or `ref` attributes, which it is not
correct
* The `priority-queue` lets declare the `capacity` attribute
together with the `message-store` attribute, which it is not
correct
* Reference documentation fixed for `channel.adoc` and `jdbc.adoc`,
doing mention about these restrictions
* Minor changes about conventions and formats applied.
Code polishing
JIRA: https://jira.spring.io/browse/INT-4015https://jira.spring.io/browse/INT-3854
Initial commit.
Reworked to emit an input stream and use the file splitter.
Add StreamTransformer.
Add CLOSABLE_RESOURCE header so we can close the session automatically.
Implement INT-3854, FTP, SFTP
(S)FTP Namespace Changes
Docs - also fixes a PDF overflow
Polishing - PR Comments
checkstyle fixes
Polishing - Add Namespace for StreamParser
Polishing - PR Comments
* Upgrade to SA and SF snapshots
* Address TODOs regarding those upgrades
* Resolve some other TODOs
* Replace `PropertyPlaceholderConfigurer` beans with the `<context:property-placeholder>`
* Upgrade to Spring Social Twitter 1.1.2 and resolve deprecations via mocks (https://github.com/spring-projects/spring-social-twitter/issues/91)
* Upgrade to Curator `3.1.0` and resolve deprecation in the `ZookeeperMetadataStore`