JIRA: https://jira.spring.io/browse/INT-4167
Since the current `ZkLock.tryLock()` is based on the fact of waiting for **at most 1 second**, that still has some timing issue for test-case, when the network delay may affect our expectation.
* Add `Thread.sleep()` with `while()` to the `ZkLockRegistryTests.testTryLock()` test to spin until successful `tryLock()`
**Cherry-pick to 4.3.x & 4.2.x**
Note: to avoid cherry-pick conflict for `4.2.x` just fully copy/paste the modified test
JIRA: https://jira.spring.io/browse/INT-4162
INT-4162: IP DSL - Phase I Connection Factories
Phase 2 - Adapters/Gateways
Phase 3 - UDP
Polishing - PR Comments
Remove unnecessary generics.
More Polishing - PR Comments
Checkstyle/Javadoc Fixes
ComponentsRegistration Improvements
Add ...Spec CTORs to avoid the issue described here:
https://github.com/spring-projects/spring-integration-java-dsl/issues/137
Also other PR comments.
Fix UDP Spec Inheritance
Jdbc Lock Test Log Adjuster
Fix Mongo Test Race Conditions
* Fox typos in the `AbstractUdpOutboundChannelAdapterSpec`
* Improve `IpIntegrationTests.testUdpInheritance()`
* Change `fixed-rate` to `fixed-delay` in the `MongoDbInboundChannelAdapterIntegrationTests-context` to pursue single-threaded environment from poller for test
JIRA: https://jira.spring.io/browse/INT-4163
When `MessageSource` is proxy, the `TransactionSynchronizationManager.getResource(this)` logic in the `MessageSource` doesn't work,
because TX resource is bound to the `Proxy` in the `SourcePollingChannelAdapter`
* Introduce `SourcePollingChannelAdapter.originalSource` property and store there a target `MessageSource` object extracted from the AOP Proxy
* Use `originalSource` as a resource to bind to the TX
* Modify `MongoDbInboundChannelAdapterIntegrationTests` to ensure that `AbstractMessageSourceAdvice` proxying the `MessageSource` doesn't effect `TransactionSynchronizationManager.getResource(this)` logic
* Refactor for some MongoDb test to rely on the `@RunWith(SpringJUnit4ClassRunner.class)` for context loading for better test class performance
**Cherry-pick to 4.3.x, 4.2.x**
Fallback to provided source if `target` from Proxy is `null`
Fix [UnusedImport] issue
https://build.spring.io/browse/INT-MASTER-415/
The `Stream` `Collectors.toList()` returns empty list if nothing pass the `.filter()`, therefore condition as `if (receiveOnlyAdviceChain != null)` is not enough
and since `SourcePollingChannelAdapter.applyReceiveOnlyAdviceChain()` doesn't have conditions as well, the target `MessageSource` is proxyed for nothing.
When `TransactionSynchronizationManager.getResource(this)` is called for the `MessageSource` it can't find it because the proxy doesn't match an original object.
* Make condition as `if (!CollectionUtils.isEmpty(receiveOnlyAdviceChain))` in the `AbstractPollingEndpoint` and `SourcePollingChannelAdapter`
* Increase group removal wait timeout in the `gemfire.DelayerHandlerRescheduleIntegrationTests`
JIRA: https://jira.spring.io/browse/INT-3770,
https://jira.spring.io/browse/INT-4107
Having `TransactionHandleMessageAdvice` we can start TX from any `MessageHandler.handleMessage()`
* Add `<transactional>` alongside with the `<request-handler-advice-chain>` for those components which produce reply
* Merge `<transactional>` and `<request-handler-advice-chain>` configuration to a single `ManagedList`
* Rework JPA `<transactional>` in favor of common solution
* Some polishing and refactoring
AbstractPollingEndpoint: avoid `new ArrayList` if we don't have `receiveOnlyAdvice`s
JIRA: https://jira.spring.io/browse/INT-4157
- Refactor the core message-driven endpoint to be `MessageProducerSupport`, eliminating the DSL wrapper
- Retain and refactor the DSL gateway wrapper - still required because it needs to be a MGS
- Port the (core) `Channels` factory
Fix Javadoc
Remove Deprecated setter
Move JmsInboundGateway to the jms Package
* Some polishing for `@Copyright`s
* Remove `@Deprecated` methods in the `Jms`
* Reinstate `IntegrationFlows.from(Function<Channels, MessageChannelSpec<?, ?>>)`
* Typos fixes in the `JmsTests`
JIRA: https://jira.spring.io/browse/INT-4133
Mostly copy/paste and changes according Java 8 and Reactor 3.0 foundations
Fix `IntegrationFlow` JavaDocs
Increase timeout in the `AbstractCorrelatingMessageHandlerTests`
Polishing - reduce timeout after first expire attempt
JIRA: https://jira.spring.io/browse/INT-4091
When `empty-group-min-timeout` is configured and `expireGroupsUponCompletion == false` and normal or partial sequences group release happens,
schedule the group for removal after `empty-group-min-timeout`, since it is empty already.
That lets to avoid `MessageGroupStoreReaper` configuration just for cleaning empty groups.
* Retrieve the group `lastModified` to check if group is still valid for removal
* Remove `ScheduledFeature` in the remove task
* Polishing for debug messages to reflect the current logic
* Reschedule empty group removal task in case of `InterruptedException` on the `lock.lockInterruptibly()`
* Fix typos in docs
Fix race condition between `groupStore.expireMessageGroups()`and `TaskScheduler` in the `AbstractCorrelatingMessageHandlerTests.testReaperReapsAnEmptyGroupAfterConfiguredDelay()`
Also check groupSize for removal decision
Address PR comments
The `JmsOutboundGateway.ReplyContainerProperties` and really can be used for options, like in the Java DSL.
Revert changes which applied package protected modifier for ctor and reinstate `public` ctor consequently
JIRA: https://jira.spring.io/browse/INT-4151
If the `MessageSource` is already a proxy, we only advise the `receive()` method.
If it's not, we advise all methods, which is incorrect.
* Use `NameMatchMethodPointcutAdvisor` in all advising cases
* Prove with the test case that only `receive()` method is advised for the `MessageSource` proxy
Polishing - PR Comments and Closeable Warnings
Eclipse emits bogus warnings with exceptions in lambdas.
Even though the lambda might run on another thread, elipse thinks it could
cause the context to not be closed.
SPR-14854: MessageChannel is now a @FunctionalInterface
* Additional Lambda polishing and some code style fixes
JIRA: https://jira.spring.io/browse/INT-3502
For some use-cases it is really useful to filter `@MessagingGateway` components as any other `@ComponentScan` capable.
* Add `useDefaultFilters()`, `includeFilters()` and `excludeFilters()` to the `@IntegrationComponentScan`
* Modify `GatewayInterfaceTests` to reflect changes and be sure that logic is applied properly
JIRA: https://jira.spring.io/browse/INT-4148
The subscribable channel incorrectly wrapped exceptions such as `MessageConversionException`
preventing the error handler from properly handling them.
Since SI-5.0 is based on Java 8 no reason to have condition for the `java.nio.Files` class in the `FileWritingMessageHandler`
Also add package protected ctors to the inner private classes in the `FileWritingMessageHandler` to avoid generated synthetic classes in case of default ctor
Address PR comments
Remove redundant log for `IOException` on `Files.move()`
JIRA: https://jira.spring.io/browse/INT-4147
By default `FileReadingMessageSource` is created without `filter`, at the same time internal `WatchServiceDirectoryScanner` is supplied with default `filter` by its `DefaultDirectoryScanner` super class.
A `DELETE` watch event condition around `FileReadingMessageSource.this.filter` is wrong, because it is `null` by default. Therefore `DELETE` events never succeed
* Modify `FileInboundTransactionTests` to accept `DELETE` watch event as well and verify that `ResettableFileListFilter.remove(File)` is performed
* Call newly created getter for `DefaultDirectoryScanner.filter` in the `WatchServiceDirectoryScanner` to assert against supplied `filter`
Polishing
**Cherry-pick to 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4144
Fixes GH-1936 (https://github.com/spring-projects/spring-integration/issues/1936)
Previously `LoggingHandler` could be used as a standalone object, without any Spring Container initialization.
Even if that doesn't sound reasonable, we should reinstate the logic to avoid breaking changes
* Initialize `expression` and `evaluationContext` during object `<init>` phase
* Some code reformatting to avoid duplicate blocks and cyclomatic complexity
* Simple code formatting
* Additional JavaDocs for `LoggingHandler`
**Cherry-pick to 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4146
Fixes GH-1942 (https://github.com/spring-projects/spring-integration/issues/1942)
Previously the `FileWritingMessageHandler` didn't wrap `new OutputStream()` to the `try...catch...finally` block, therefore any errors on that (e.g. `FileNotFoundException` because of permissions) cause an early exist without `inputStream.close()`
* Move a `new OutputStream()` to the `try...catch`
* Change `destinationDirectory.canWrite()` to the `Files.isWritable(destinationDirectory.toPath())` because the first one doesn't work on Windows
**Cherry-pick to 4.3.x and 4.2.x but without Files.isWritable() change**
JIRA: https://jira.spring.io/browse/INT-4145
Strange stubbing failure on spied template.
Perhaps some JIT interaction since the method is used normally before stubbing.
Change the spy to a mock for the last part of the test.
Remove comment before the mock since it isn't relevant any more
JIRA: https://jira.spring.io/browse/INT-2460,
https://jira.spring.io/browse/INT-4122
Since the main purpose of the `MessageStore` to persist message for durability and only,
it doesn't make sense to modify `Message` for additional headers like `SAVED` and `CREATED_DATE`.
Such a logic should be a part of metadata stored together with the message.
And it is provided by the out-of-the-box `MessageStore` implementation.
In addition we free ourselves from the reflection operations to retain `ID` and `TIMESTAMP` headers when we add `SAVED` and `CREATED_DATE`
* Control "already saved" logic in the `JdbcMessageStore`s via `DuplicateKeyException` on the `INSERT`.
This is much effective then additional `SELECT` in case of `SAVED` before
* Control "already saved" logic in the `AbstractConfigurableMongoDbMessageStore` via `DuplicateKeyException` on the `INSERT`.
Since `MongoDbMessageStore` doesn't provide extra `messageId` field, perform extra `SELECT` before store document.
Anyway the `MongoDbMessageStore` isn't recommended for use.
We may consider to deprecate it
* Control "already saved" logic in the `AbstractKeyValueMessageStore` via `putIfAbsent` operation
With this fix we persist message in the store as is without any modifications when we perform standard serialization procedure.
Any custom serializers should consider to use `MutableMessageBuilder` if there is a requirement to retain `ID` and `TIMESTAMP`
Rework `MongoDbMetadataStore.putIfAbsent()` to normal `findAndModify()` with particular `$setOnInsert`.
Technically the MongoDB query looks like:
```
db.collection.findAndModify({
query: { _id: $key },
update: {
$setOnInsert: { value: $value } // perform modification only on upsert
},
new: false, // don't return new doc if one is upserted
upsert: true // insert the document if it does not exist
})
```
Move single import to the appropriate JavaDoc
Polishing after rebase
DEBUG messages in `doStoreIfAbsent()` implementations
* To keep track of the extra message information in the `MessageStore`, without `Message` modification, introduce `MessageMetadata` and `MessageHolder`
* Add `MessageStore#getMessageMetadata()`
* Modify MongoDb `MessageStore` to add extra `timestamp` for individual message
* Fix `ConcurrentAggregatorTests` race condition.
Since currently the default release strategy is `SimpleSequenceSizeReleaseStrategy` which is just based on the `MessageGroup` size, there is no guaranty which messages will complete the group in concurrent environment.
The test is really based on the `SequenceAwareMessageGroup` logic to discard the message with the same `correlationId`
Fix `@Copyright` format
Move cast to `MessageHolder` after `Assert.isInstanceOf(MessageHolder.class, messageHolder)`
Retain backward compatibility in the `AbstractKeyValueMessageStore`
Polishing
JIRA: https://jira.spring.io/browse/INT-4137
Aggregators with `SequenceSizeReleaseStrategy` do not perform well with large groups
because of an O(n) linear search to reject (discard) duplicate sequences.
Change the aggregator to use a `SimpleSequenceSizeReleaseStrategy` by default, unless
`setReleasePartialSequences(true)`.
This avoids the linear search, which is not needed for most splitter -> ... -> aggregator
flows.
Log a warning if SSRS is used.
Polishing - PR Comments
* Remove `this.logger.isWarnEnabled()` since it is redundant when our log message is just string constant
JIRA: https://jira.spring.io/browse/INT-3825
Rework `MessagingMethodInvokerHelper` logic to accept non-public methods with Messaging annotations as candidates for invocation
Adjust SpEL configuration in the `MessagingMethodInvokerHelper` to deal with `declaredMethods()`, not only `public`
Honor caching in the `MethodReference`
JIRA: https://jira.spring.io/browse/INT-832
When we scan directory recursively for files (e.g. `WatchServiceDirectoryScanner`), it can be useful to get access to the relative path from the `Message`, e.g. on the `FileWritingMessageHandler` side to restore the original structure
* Add a `FileHeaders.FILENAME` into the outbound `Message` from the `FileReadingMessageSource`
* The result of that header is like a removal of leading `this.directory.getAbsolutePath()` in the target `File.getAbsolutePath()`.
In case of not recursion we get just only regular file name.
* Introduce `FileHeaders.RELATIVE_PATH`
* Populated `FileHeaders.RELATIVE_PATH`, `FileHeaders.FILENAME`, `FileHeaders.ORIGINAL_FILE` in the `FileReadingMessageSource`
* File `FileTailingMessageProducerSupport` to populate `FileHeaders` properly
* Introduce ctor for the `LastModifiedFileListFilter` for better Java configuration experience
* Add docs for changes
Doc Polishing
JIRA: https://jira.spring.io/browse/INT-4119
* Mark `MessageDocument` with the `@AccessType(AccessType.Type.PROPERTY)` for better performance via bean accessors
* Add more getters for `MessageDocument` properties
* Leave `MessageWrapper` as is since it has a complex internal logic which may be broker via accessors
JIRA: https://jira.spring.io/browse/INT-3903
According to RFC-6648, the "X-" prefix has been deprecated and now any use-specific headers can be mapped without any prefix
* Fix `DefaultHttpHeaderMapper` for the `""` as a `userDefinedHeaderPrefix` by default
Document `X-` changes
JIRA: https://jira.spring.io/browse/INT-4135
The incoming `Content-Type` HTTP header can be in any arbitrary case.
Fix `DefaultHttpHeaderMapper` `Content-Type` header re-mapping to the `MessageHeaders.CONTENT_TYPE` via `equalsIgnoreCase()` comparison
**Cherry-pick to 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4131
Specify an expression on the outbound endpoints to set the `x-delay` header when
using the RabbitMQ Delayed Message Exchange plugin.
Polishing
- PR Comments
- Add `setDelay`
- Port `FunctionExpression` from DSL
- Add `SupplierExpression`
Javadoc Fixes
Use ValueExpression for delay
* Simple polishing for `SupplierExpression`
* Mention plain `delay` property in the `amqp.adoc`
JIRA: https://jira.spring.io/browse/INT-4132
The race condition is present when polling task may be ran before `MessageSource<?>` has been started.
* Swap the order of `start()` in the `SourcePollingChannelAdapter`.
Since proxying is now applied only for the `MessageSource.receive()` it doesn't hurt to start it before actual proxying.
Just because it is really should be started before performing its `receive()`
* Prove the proper order with the mock test and protect ourselves for the future similar changes
* Also swap the `stop()` order in the `SourcePollingChannelAdapter.
We have to stop/cancel the polling task before discarding internal `MessageSource` lifecycle.
For example with the current state we may close an underlying resource already, but still have the last polling tick.
That may cause any unexpected behaviour
**Cherry-pick to 4.3.x**
Polishing
JIRA: https://jira.spring.io/browse/INT-4118
Add an option to the `CharacterStreamReadingMessageSource` to detect EOF
on the stream and close the context.
Publish event instead of closing context.
Polishing - PR Comments
Polishing
Docs about stopping the poller.
* Fix typos in the docs
JIRA: https://jira.spring.io/browse/INT-4127
Fixes GH-1913 (https://github.com/spring-projects/spring-integration/issues/1913)
The current `tryLock()` implementation with the `0` timeout to wait for underlying `InterProcessMutex` answer makes this function almost fully impossible
* Fix `ZkLock.tryLock()` to delegate with the `tryLock(1, TimeUnit.SECONDS)` to give some time window chance for network communication.
It isn't ideal for the `tryLock()` contract, but at least it is better then don't let the feature to work at all.
**Cherry-pick to 4.3.x & 4.2.x**