https://build.spring.io/browse/INT-SI50X-JOB1-56
We can't wait for the latch in the interruptable code flow;
we can't have a round-robing election guarantees.
* Add `Thread.sleep(LockRegistryLeaderInitiator.this.busyWaitMillis)`
to the `LockRegistryLeaderInitiator` when we restart the main task
* Remove latches waiting and thread shifting from the
`RedisLockRegistryLeaderInitiatorTests`
* Use long `busyWaitMillis` for yielding initiator to let the second
candidate to be elected
**Cherry-pick to 5.0.x**
(cherry picked from commit 081d0d1)
https://build.spring.io/browse/INT-FATS5IC-501/
When we try to wait for the `Latch` in the interruptable code flow,
it is a fact that we step away from the waiting and end up with the
race condition downstream.
* Wrap `Latch` in the interruptable `publishOnRevoked()` code to the
`Executor.execute()`
* Remove `deleteTimeoutMillis` option from the `RedisLockRegistry`
since it doesn't make sense in the interruptable code.
* Add `RedisLockRegistry.setExecutor()` to allow to inject an external
`Executor`
* Add more debug logging into the `LockRegistryLeaderInitiator`
**Cherry-pick to 5.0.x**
(cherry picked from commit 51c4951)
https://build.spring.io/browse/INT-MASTER-1024
When the Lettuce Redis client catches an `InterruptedException`, it is
wrapped to the `RedisCommandInterruptedException`, therefore when we
catch an exception on our code level it is not an `InterruptedException`
anymore and we can't proceed in the loop because the tread is
`interrupted` already.
* Check the `interrupted` alongside with the `InterruptedException`
to restart a loop from a fresh thread.
**Cherry-pick to 5.0.x**
(cherry picked from commit fc47952)
* Use Lettuce Redis client; Redis module fixes
The Lettuce client is based on the Netty and more stable, than Jedis
therefore we get a performance improvement for tests
(it saves us at about 30 seconds).
Also this client doesn't fail for me on Windows sporadically (very often)
with the `ConnectionClosedException`
* After switching to the Netty-based client, we expose the interrupted
Thread issue in the `LockRegistryLeaderInitiator`.
If we interrupted (expected behavior), we try to unlock calling
`RedisLockRegistry`, but Netty client reject our request because the
thread is interrupted, therefore we never delete the lock when we yield
our leadership.
Fix the issue with shifting a `RedisTemplate.delete()` operation to the
`ExecutorService` when the current thread is interrupted
* Allow to configure such an `ExecutorService` and timeout to wait for
the `submit()` result
* Refactor `RedisAvailableRule` and all the Redis tests do not expose
the target `RedisConnectionFactory` implementation.
* Make all the test-cases based on the `connectionFactory` created by
the `RedisAvailableTests.setupConnectionFactory()`
* Tweak some unnecessary timeouts and sleeps for better tests task
throughput
* Add a `Log4j2LevelAdjuster` into the `RedisLockRegistryLeaderInitiatorTests`
JIRA: https://jira.spring.io/browse/INT-4461
Convert `byte[]` to `String` using `URF-8` by default.
Add optional evaluate methods to JsonPathUtils with a Charset to use when
converting `byte[]` to `String`.
This is not currently exposed using SpEL. It can be done, but probably not worth
the effort until somebody asks for it.
**cherry-pick to 5.0.x, 4.3.x**
* Use `BAIS`
(cherry picked from commit e987387)
* INT-4458: Do not expose recursive generics API
JIRA: https://jira.spring.io/browse/INT-4458
According Kotlin generics system restrictions we can't expose API
based on the recursive generics, like we have with Java DSL for JMS
* Replace explicit recursive generics on factory method with the wildcard (`?`).
This way both Kotlin and Java are able to instantiate target object and perform
the proper chain API auto-completion
* Fix `JmsInboundChannelAdapterSpec` to deal with provided `S` type for the
`configureListenerContainer()` - the way we can configure a `JmsDefaultListenerContainerSpec`
* Add `kotlin-spring` Gradle plugin to avoid extra `open` modificator on `@Bean` methods
* Add `JmsDslKotlinTests.kt`
**Cherry-pick to 5.0.x excluding Kotlin support**
* Fix `Amqp` DSL factory for recursive generics
* Polishing for Kotlin tests
JIRA: https://jira.spring.io/browse/INT-4456
Since Kotlin compiles lambdas different way than Java, they are not
synthetic classes at runtime anymore.
Therefore we fallback to the method invocation logic, but since Java 8
interfaces has `default` methods as well the `MessagingMethodInvokerHelper`
can't select the target method for invocation
* Use explicit `Function.apply()` for non-synthetic implementations
* Add `RouterDslTests` Kotlin-based test-case
**Cherry-pick to 5.0.x**
* Add more explicit methods for invokers
The `transactionWithCommitAndAdvices()` uses `SimpleRepeatAdvice`
which essentially performs `doPoll()` twice.
In this case we don't have enough messages in the `goodInputWithAdvice`
queue
* Add one more message to the `goodInputWithAdvice` queue during testing
* Increase all the timeouts
* Increase capacity in queues for the `transactionWithCommitAndAdvices()`
**Cherry-pick to 5.0.x and 4.3.x**
(cherry picked from commit 000f297)
JIRA: https://jira.spring.io/browse/INT-4455
When using java config, `setChannelMapping` NPEs due to no AC.
**cherry-pick to 4.3.x, and to master, removing AC check**
* Polishing - PR comment
* INT-4446 Improve EmbeddedJsonHeadersMessageMapper
JIRA: https://jira.spring.io/browse/INT-4446
* Do not recreate message if not necessarily
* Do not let to generate `id` and `timestamp` if they are not mapped
* Use `smartMatch` to allow to configure negative patterns
* Introduce `PatternMatchUtils.smartMatchIgnoreCase()` for convenience
**Cherry-pick to 5.0.x**
* * Polishing `EmbeddedJsonHeadersMessageMapper`
JIRA: https://jira.spring.io/browse/INT-4447
When we get an exception during `this.lock.unlock()`, we don't revoke
leadership.
In case of external resource (e.g. JDBC) this may cause a race condition
when the second candidate is selected as leader when connection comes back
* Catch `this.lock.unlock()` exceptions and log them under DEBUG.
This way we proceed to the `handleRevoked()` logic
**Cherry-pick to 5.0.x and 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4438
The `SmartLifecycleRoleController` is based on the `MultiValueMap`
which used internally a `List` for the values.
With such an architecture we can add the same value several times.
On the other hand we are iterating over `Lifecycle`s in the role and
build a `Map` for their running status.
In this case when `NamesComponent`s return the same name the Java
`Collectors.toMap()` fails with a duplicate key error.
In any cases it would be better do not allow to add the same lifecylce
several time to the role or different with the same name.
* Add search logic to the `addLifecycleToRole()` to fail fast with the
`IllegalArgumentException` because a lifecycle with the same name is
already present in the role
**Cherry-pick to 5.0.x**
* Remove redundant `this.initialized = false` from the
`AbstractPollingEndpoint.doStop()`
Add `allEndpointsRunning()` verification to the `EndpointRoleParserTests`
Polishing
https://build.spring.io/browse/INT-SI50X-20
Looks like 5 seconds is not enough to wait for the test completion,
especially on CI server
* Refactor `PollingConsumerEndpointTests` to use `OnlyOnceTrigger`
from the test-support module instead of local `Trigger` implementation
* Increase timeout for latch in the `OnlyOnceTrigger` to 10 seconds
**Cherry-pick to 5.0.x**
(cherry picked from commit a65d05c)
JIRA: https://jira.spring.io/browse/INT-4440
The previous fix eliminated an extra `generateId()` call, but at the
same introduced regression do not populate `id` and `timestamp` from
the serialized state, e.g. after JSON transferring over the network
* Introduce a couple utility methods in the `MutableMessageHeaders`
to extract and parse `id` and `timestamp` from the provided headers
**Cherry-pick to 5.0.x**
(cherry picked from commit ae2aa8b)
JIRA: https://jira.spring.io/browse/INT-4441
Possible concurrent updates to `AbstractCorrelatingMessageHandler.groupIds` and
`expireGroupScheduledFutures`.
(cherry picked from commit f9d5198)
JIRA: https://jira.spring.io/browse/INT-4434
There were a restriction introduced since Java DSL `1.2` do not use
`IntegrationFlow` beans for sub-flow definitions, e.g. in routers.
It is considered as regression by community because it worked before
in version `1.1`
* Introduce `IntegrationFlow.getInputChannel()` to be able to bridge
from the main flow to the flow which is treated as sub-flow.
In most cases we talk about an independent bean for the `IntegrationFlow`
which can be used as a stand along one and as a sub-flow in other flow
**Cherry-pick to 5.0.x**
Add JavaDocs to the `EndpointSpec.obtainInputChannelFromFlow()`
JIRA: https://jira.spring.io/browse/INT-4433
The current `MessagePublishingInterceptor` behavior is to parse expressions
on each method invocation what is not so efficient at runtime
* Introduce `default` `Expression`-based method to the `PublisherMetadataSource`
contract and call existing String-based methods for backward compatibility.
* Deprecate String-based `PublisherMetadataSource` methods in favor of newly
introduced `Expression`-based
* Implement new `getExpressionForPayload()` and `getExpressionsForHeaders()`
in all the `PublisherMetadataSource` implementations
* Cache parsed `Expression` s during initialization in the `PublisherMetadataSource`
implementations or do that on demand in the `MethodAnnotationPublisherMetadataSource`
by provided method basis
* Introduce `MethodAnnotationPublisherMetadataSource#metadataCacheLimit` and populate
its value from the `@EnablePublisher` or `<int:annotation-configuration>`
* Implement `entrySet()` and `values()` in the `ExpressionEvalMap`
**Cherry-pick to 5.0.x**
* Add `@SuppressWarnings("varargs")` to avoid compilation warning
* Remove LRU cache logic - it's fine to cache all the info about methods
in the classpath
For better traceability for errors during lock acquiring add DEBUG
logging message in the `catch` block before returning back to the main
loop for the next acquiring attempt
**Cherry-pick to 5.0.x and 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4437
The `ScatterGatherHandler` overrides a `replyChannel` header for the
scatter message to its internal queue and doesn't reinstate the original
`replyChannel` header when producer a gather result message
* Rebuild gather result message with population a proper `replyChannel`
header from the request message and removing a `gatherResultChannel`
header
**Cherry-pick to 5.0.3 and 4.3.x**
Polishing
JIRA: https://jira.spring.io/browse/INT-4430
When Iterator-based `FileSplitter` splits the file, and an exception
throws in downstream flow (in the same thread), the exception propagates
to the caller leaving underlying file reader opened.
This commit changes `AbstractMessageSplitter` the way, that,
when any exception happens, if Iterator implements `java.io.Closeable`,
its `close()` method will be called before propagating exception.
Also `FileSplitter`'s underlying iterator implements `Closeable` now.
* Make `CloseableIterator` to follow `Closeable` contract.
Now `CloseableIterator.close()` declares `IOException` and can be used
as base interface for `FunctionIterator`.
* Adjust tests.
Adjust tests to reflect the fact that we call `close()` on the reader
one more time in the end of iterator.
**Cherry-pick to 5.0.x and 4.3.x**
(cherry picked from commit 7f25cba)
JIRA: https://jira.spring.io/browse/INT-4428
Using `increaseNestingLevel()` and `decreaseNestingLevel()` is not
thread-safe and may cause a race conditions
* Use `MethodParameter.nested()` instead which creates and cache a new
`MethodParameter` for the nested generic type
**Cherry-pick to 5.0.x**
Fixesspring-projects/spring-integration#2388
During `HeaderEnricherSpec` refactoring the `adviceChain` population
has been missed, alongside with many other `AbstractReplyProducingMessageHandler`
options from the `ConsumerEndpointSpec`
* Refactor `HeaderEnricherSpec` to build `HeaderEnricher` and an
appropriate `MessageTransformingHandler` from the ctor to be able
to pick up an `adviceChain` automatically in the `ConsumerEndpointSpec.get()`
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4423
Add a facade on top of micrometer so the dependency can
be optional.t
Next iteration - PR comments
Checkstyle
More polishing; static classes etc.
checkstyle
Further polishing; docs; auto-register `MicrometerMetricsCaptor`.
Polishing - move captor load to a static method on the captor.
* Fix Checkstyle violation
* Some code style polishing
JIRA: https://jira.spring.io/browse/INT-4417
Provide more flexibility with bean naming when using EIP Annotations with
Java configuration.
* Polishing - PR Comments
* More polishing - remove `@Inherited`; disallow with more than one EIP annotation.
JIRA: https://jira.spring.io/browse/INT-4421
If a component invoked by an SPCA threw a `MessagingException` with no
`failedMessage`, the resulting ErrorMessage payload had no `failedMessage`.
The `UnicastingDispatcher` had a check for this so it wasn't an issue
as long as at least one `DirectChannel` was between the poller and the
component.
Promote the wrapping code to `IntgrationUtils` and invoke it from
places that blindly rethrew `MessagingException`s.
JIRA: https://jira.spring.io/browse/INT-4418
Add docs for the rework and optimize `Meter` creation.
Polishing
* Polishing according PR comments
* Fix typo in `dsl.adoc`
https://build.spring.io/browse/INT-FATS5IC-430
Looks like there is a race condition when our polling rate around
data base is too fast and we have access to the DB files even during
application context close.
* Stop polling channel adapter in the tests explicitly after test methods
* Increase some tests performance decreasing timeouts to wait
* Upgrade to Reactor-3.1.5, AssertJ-3.9.1, Derby-10.14.1.0 and some
Gradle plugins
* Upgrade to `reactor-netty-0.7.5`
* Remove workaround from the `StompServerIntegrationTests`
* Upgrade to Spring Data Kay SR5
* Upgrade to Spring Security 5.0.3
* Increase timeouts and performance in the `StreamTransformerParserTests`
If there is `json`-aware `contentType` header in the message to process
and payload type is `String` or `byte[]` and it isn't equal to the
expected exclusive method argument type (even generic from the `Message<>`),
the conversion should happen only if SpelInvoker is no method.
The regular `InvocableHandlerMethod` takes care about payload conversion
via configured `MessageConverter` in the `PayloadArgumentResolver`
* Fix `MessagingMethodInvokerHelper` to call JSON conversion only when
`this.handlerMethod.spelOnly`
NOTE: We can't do generics conversion right now because it is going
to be a breaking change around
`org.springframework.integration.support.json.JsonObjectMapper` property
in the `MessagingMethodInvokerHelper`.
We can do that only in `5.1` and rely there only on the functionality
from the Jackson Object mapper
* Convert from JSON only in the `invokeExpression()`
* Optimize message recreation only if target param type is `Message`.
Otherwise override just `payload` property of the `ParametersWrapper`
JIRA: https://jira.spring.io/browse/INT-4413
When we override entity in the `IntegrationFlowContext.registry`,
we may get dangling beans in the application context,
when the structure of a new `IntegrationFlow` is different.
* Fix `IntegrationFlowContext` to disallow to override the flow
registration under the same name
* Add JavaDocs to the `IntegrationFlowRegistrationBuilder` methods
* Add `toString()` to the `IntegrationFlowRegistration` and
`StandardIntegrationFlow` to make the logging of these components
friendlier
JIRA: https://jira.spring.io/browse/INT-4411
The `RouterSpec.RouterMappingProvider` relies on the
`ContextRefreshedEvent` which happens only during application start up.
When we register `IntegrationFlow` at runtime, this event doesn't
happen and therefore sub-flow mappings don't populated.
* Fix `RouterSpec.RouterMappingProvider` to parse sub-flow mappings in
the `onInit()`
* Reorder components registration for the router in the
`IntegrationFlowDefinition` to let lately sub-flows to start earlier,
then lifecycles in the main flow
JIRA: https://jira.spring.io/browse/INT-4410
The `CollectionArgumentResolver` has been introduced especially for the
cases to work with `MessageGroupProcessor` (an aggregator)
when the payload is a `Collection<Message<?>>`.
This use-case doesn't apply for the general collection parameter use-case.
* Register `CollectionArgumentResolver` only when `listCapable` option.
For all other collection-based use-cases fallback to the standard
`PayloadArgumentResolver` with an appropriate configured `MessageConverter`
Note: this is for backward compatibility.
In the `5.1` we may reconsider to use `MessageConverter` in the
`CollectionArgumentResolver` as well, or just remove it altogether with
an appropriate logic in the `PayloadArgumentResolver`, since this
`CollectionArgumentResolver` solution isn't robust
JIRA: https://jira.spring.io/browse/INT-4402
Make `GlobalChannelInterceptorProcessor` as a `BeanPostProcessor`,
so it can apply global `ChannelInterceptor`s to any initialized channel
beans, even those created at runtime, like in case of dynamic flows with
Java DSL
**Cherry-pick to 4.3.x**
* Add `postProcessDynamicBeans` global property with `false` by default
* Rely on the `postProcessDynamicBeans` property in the
`GlobalChannelInterceptorProcessor.postProcessAfterInitialization()`
* Add `postProcessDynamicBeans=true` to the
`GlobalChannelInterceptorTests-context.xml` to be sure in the test-case
that option works
* Document the option and effect from the global channel interceptors
JIRA: https://jira.spring.io/browse/INT-4402
Previously, Micrometer instrumentation was only applied to components during
ApplicationContext initialization.
`IntegrationManagementConfigurer` is now a `BeanPostProcessor` as well as a
`SmartInitializingSingleton`, but only acts as a BPP after the context is
initialized. This enables Micrometer instrumentation to beans added later,
either via a new `BeanDefinition` or `bf.initializeBean`.
NOTE: destroying and re-creating a bean will use the same `Meters`.
JIRA: https://jira.spring.io/browse/INT-4396
When target distributed `Lock` implementation throws an exception, e.g.
in case of no connection to the service, the `LockRegistryLeaderInitiator`
exists the loop and can come back to the elections only after restart
* Catch all the exception on `this.lock.tryLock()` and resubmit
`LeaderSelector` for a new locking cycle if
`LockRegistryLeaderInitiator.isRunning()` and `InterruptedException`
* Remove diagnostics from the `JdbcLockRegistryLeaderInitiatorTests`
since this fix confirms that we just didn't have a reconnect logic before
when this test failed sporadically
**Cherry-pick to 4.3.x**