Resolves https://github.com/spring-projects/spring-integration/issues/3600
Previously, the `KafkaProducerMessageHandler` did not synchronize a transaction
with some other transaction (e.g. JDBC); it published in a local transaction instead.
Also configure the Gradle Kotlin Daemon to work with JDK 16.
**cherry-pick to 5.4.x**
Related to https://build.spring.io/browse/INT-MAIN-84/
The `lock.unlock()` must be called in the `finally` block of the
nested `try..catch`, not in the outer which may just fail on `lock.lockInterruptibly()`
in which case there is just not going to be anything we can `unlock()` in the end
**Cherry-pick to `5.4.x` & `5.3.x`**
* Add `org.springframework.integration.history` to trusted default packaged of the `JacksonJsonUtils`
* Add `@JsonCreator` to `MessageHistory` `private` ctor to let it to be created automatically by Jackson
* Add `equals()` and `hashCode()` into `MessageHistory` for the proper `Message` comparison
* Add `MessageHistory` into headers for testing with Redis JSON (de)serialization
**Cherry-pick to `5.4.x` & `5.3.x`**
The `spring.integration.properties` can come with the `noAutoStartup`
property where we can specify a source polling channel adapter endpoint to
not start automatically.
Turns out the `SourcePollingChannelAdapterFactoryBean` propagates its
`autoStartup` property unconditionally which will skip the `noAutoStartup` value
because an `AbstractEndpoint.setAutoStartup()` sets an `autoStartupSetExplicitly` state
* Fix `SourcePollingChannelAdapterFactoryBean` to rely on a `Boolean` object state
and don't call target endpoint `setAutoStartup()` if it was not set
* Adjust `spring.integration.properties` in tests to use `noAutoStartup`
for some `SourcePollingChannelAdapterFactoryBean`
* Verify that property was applied in the `IntegrationFlowTests.testWithSupplierMessageSourceImpliedPoller()`
**Cherry-pick to `5.4.x` & `5.3.x`**
The `@Indexed` comes without any attributes, but it is included
into a chain via `importingClassMetadata.getMetaAnnotationTypes(ann)`.
So, skip attributes from meta annotation when it is `null`
**Cherry-pick to `5.4.x` & `5.3.x`**
We fail with `NoClassDefFoundError` when we use `@EnableIntegrationGraphController`
in WebFlux env without Spring MVC.
Another issue that we don't register CORS for WebFlux
* Extract top-level package protected classes for MVC and WebFlux to register CORS
in the appropriate environment according classpath
* Adjust `HttpIntegrationConfigurationInitializer` and `WebFluxIntegrationConfigurationInitializer`
for native compatibility
* Add `@Indexed` for `@MessagingGateway` for indexer support in Spring Boot and Spring Native
**Cherry-pick to `5.4.x` & `5.3.x`**
# Conflicts:
# spring-integration-http/src/main/java/org/springframework/integration/http/config/IntegrationGraphControllerRegistrar.java
Fixesspring-projects/spring-integration#3570
The module file with the Gradle metadata cannot be published on Maven
Central, which causes issues for some people using a repository manager such
as Artifactory. If it doesn't return a 404 HTTP status, the build fails
instead of ignoring the module.
**Cherry-pick to `5.4.x` & `5.3.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3567
* Retry for TransactionSystemException in JdbcLockRegistry
* Unit test added for `TransactionSystemException`
* Completing author and copyright year information
**Cherry-pick to `5.4.x` & `5.3.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3560
According RFC 5322 `FROM` and `REPLY-TO` received mail message can be
as an array of addresses.
* Fix `MailUtils` to present those arrays as comma-delimited strings for
Spring message headers
* Fix tests to deal already with several addresses for `FROM` mime header.
In the future we may change the logic to map those mime headers to arrays
as it states according the mentioned RFC
**Cherry-pick to `5.4.x` & `5.3.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3558
Kotlin lambdas mostly used to configure endpoints in DSL manner
are not really Java lambdas, but rather anonymous classes implementing
respective Java interfaces.
While in most cases such classes carry generic info for their method impls
properly in Java, it is somehow doesn't work well for `GenericHandler`
implemented by Kotlin lambdas
* Wrap provided `GenericHandler` in the `BaseIntegrationFlowDefinition.handle()`
into a Java lambda and call `handle()` recursively to carry an expected type to
the `LambdaMessageProcessor`
* Fix `LambdaMessageProcessor` to handle `ClassUtils.isKotlinUnit()` result of
an invocation as a `null` reply
**Cherry-pick to `5.4.x` & `5.3.x`**
* GH-3554: Eval remote dir on each synchToLocal
Fixes https://github.com/spring-projects/spring-integration/issues/3554
The `remoteDirectoryExpression` was introduced into an
`AbstractInboundFileSynchronizer` to let end-user to evaluate a remote directory
on each poll (essentially on each `synchronizeToLocalDirectory()` call).
The fix for the https://jira.spring.io/browse/INT-4491 introduced a regression
when such an expression was evaluated only once when we call a `setRemoteDirectory()`.
So, an original purpose of this option was lost and we don't get an actual
remote dir on each poll
* Remove `evaluateRemoteDirectory()` method and its usage since it doesn't
reflect expectation of the remote dir expression property
* Reinstate the `remoteDirectoryExpression` evaluation in the
`synchronizeToLocalDirectory()`
* Propagate the result of that expression into further methods for copying
files
* Remove setting of the `remoteDirectory` variable into a global `EvaluationContext`
of the `AbstractInboundFileSynchronizer` instance since it is not thread-safe
* Instead create an `EvaluationContext` locally for each `synchronizeToLocalDirectory()`
call and set the `remoteDirectory` variable into this scoped instances
* Generate a local file name from the `localFilenameGeneratorExpression`
against locally created `EvaluationContext` with the mentioned `remoteDirectory` variable
* Cover the expected functionality with a unit-test
**Cherry-pick to `5.4.x` & `5.3.x`**
* * Fix `testRemoteDirectoryRefreshedOnEachSynchronization` according PR review
SO: https://stackoverflow.com/questions/67214907/zeromq-with-spring-spring-integration-zeromq
The `Mono` is created in several places in ZeroMQ components from their constructors.
That leads to the reactive stream to be configured just after ctor, which will ignore
any changes to the options which are used from that `Mono` definition.
For example this code `.doOnNext(this.sendSocketConfigurer)` is done once during
reactive stream definition.
* Fix all the ZeroMQ components to defer usage of the options which could be changed
after ctor initialization
* Cover affected option changes in the tests
**Cherry-pick to `5.4.x`**
The `AbstractPersistentAcceptOnceFileListFilter`
extends now an `AbstractDirectoryAwareFileListFilter`
and makes all the implementors to implement its `isDirectory()` method.
This is a breaking change in the point release which makes implementations
outside of the core project not compilable
The regression after: https://github.com/spring-projects/spring-integration/issues/3488
Related fix in the Spring Cloud GCP: https://github.com/spring-cloud/spring-cloud-gcp/pull/2654
* Implement an `isDirectory()` in the `AbstractPersistentAcceptOnceFileListFilter`
to let other implementations do not worry during upgrade
**Cherry-pick to `5.4.x` & `5.3.x`**
Related to: https://github.com/spring-cloud/stream-applications/issues/156
The `IntegrationReactiveUtils` uses a general `Flux.retry()`
operator to always retry for all the errors.
On the other hand it has only a `.doOnError(MessagingException.class)`
which leads swallowing all the other exceptions from logs and handling.
* Replace with `retryWhen()` for the `MessagingException` predicate
failing for all other exceptions.
The end-user may add their own `retry` or error handling mechanism to
the returned `Flux` from the `IntegrationReactiveUtils`
**Cherry-pick to 5.4.x**
`IMAPFolder.idle()` by default keeps idle-ing after each response.
We don't need that, because we want to fetch the new mails immediately (over the same connection).
To make `idle()` not keep on going, we called
`folder.isOpen()` which in most cases makes `idle()` stop by calling `noop()`
internally (to keep the connection alive) which leads to the current
`idle()`-call being canceled.
The problem this commits addresses is that the call to `noop()` only
happens if there were no calls in the last second.
There is a check for that in `com.sun.mail.imap.IMAPFolder.keepConnectionAlive`.
So if a new message appears less then a second after idle started, we will miss it.
This new way interrupts `idle()` more often than before, e.g. when there
is an expunge-message (i.e. a message was deleted), which we don't care about.
But the subsequent `receive()` in IdleTask will simply get no
messages and then turn around and start idle-ing again.
**Cherry-pick to `5.3.x` & `master`**
Resolves https://github.com/spring-projects/spring-integration/issues/3526
`FailoverClientConnectionFactory`
The logic to detect we had iterated over all factories and including
the one from which the previous connection was established was incorrect,
causing an infite loop until one of the factory connections was successful.
Change the logic to detect we have reset the iterator and the current failure
is from the same factory as the one from which the previous connection was
established.
**cherry-pick to 5.4.x, 5.3.x**
* Add diagnostics.
* Fix race in test.
* More race fixes and diagnostics.
* Remove diagnostics.
* GH-3521: Delayer: schedule release task with TX
Fixes https://github.com/spring-projects/spring-integration/issues/3521
There is a race condition when transactional `MessageStore` is used
for `DelayHandler`, so the message is not visible for reads until after TX is
committed, but a scheduled release task may be already ready after delay
* Register a `TransactionSynchronization` with scheduling a releasing task
when TX is committed
**Cherry-pick to `5.4.x` & `5.3.x`**
* Fix language in delayer.adoc
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
Resolves https://github.com/spring-projects/spring-integration/issues/3523
- `TcpNetConnection` - publish open event on reader thread to avoid race with first read.
- Intercepted connections - Ensure that the event source is always the outermost interceptor.
- Also reduce delays during NIO client connect.
**cherry-pick to 5.4.x, 5.3.x**
5.3.x will require cherry picking GH-3509 commits.
# Conflicts:
# spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpNetServerConnectionFactory.java
Resolves https://github.com/spring-projects/spring-integration/issues/3509
When a connection was intercepted, the `TcpSender.add...` was called with the
interceptor, but the `removeDead...` was called with the actual connection,
causing a memory leak.
Always call the `TcpSender` with the outer-most interceptor.
Fixes https://github.com/spring-projects/spring-integration/issues/3509
Dead connections are not being removed on `TcpSender` when using a `TcpConnectionInterceptor`.
May cause a memory leak
* Fix `TcpConnectionInterceptorSupport` to override `registerSenders()`
and delegate to the `this.theConnection`
* Introduce vararg-based `setInterceptor()` into `TcpConnectionInterceptorFactoryChain`
* Remove redundant `//NOSONAR` and properly return an `Arrays.copyOf()` in the `getInterceptorFactories()`
**Cherry-pick to `5.4.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3507
The `OSDelegatingFileTailingMessageProducer` passing command string to `Runtime.getRuntime().exec()`
may cause problems if spaces (and other special characters) are used in the filename.
* Use an array for command and its options to let the target `Runtime` to parse and
execute it properly
**Cherry-pick to 5.4.x, 5.3.x & 5.2.x**
Fixes https://github.com/spring-projects/spring-integration/issues/3497
The `BaseIntegrationFlowDefinition.REFERENCED_REPLY_PRODUCERS` is filled up
only with the `MessageProducer` instances.
Therefore no reason to calculate a hash code for every single bean passed
to the `ReplyProducerCleaner.requiresDestruction()`
* Check for the `MessageProducer` instance before passing the bean to the
`BaseIntegrationFlowDefinition.REFERENCED_REPLY_PRODUCERS.contains()`
* Check for the `MessageProducer` in the `ReplyProducerCleaner.postProcessBeforeDestruction()`,
too.
It can be called independently of the `requiresDestruction()` and will calculate a hash code
from the bean again for nothing
**Cherry-pick to 5.4.x & 5.3.x**