* INT-4480: Use component type for ids in the flow
JIRA: https://jira.spring.io/browse/INT-4480
For better readability of bean names, e.g. from the metrics collectors,
generate them from the component type instead of their fully qualified
class names
* * Fix bean name for injection in the WebFluxDslTests
JIRA: https://jira.spring.io/browse/INT-4457
When an `IntegrationFlow` is reply-based (we expect a reply in the
beginning) and `log()` (or `wireTap()`) is used in the end, we are
forced to add an empty `bridge()` in the end to ensure a `replyChannel`
header routing
* Fix `IntegrationFlowDefinition` to add `enrichHeaders()` in the end
to populate a `nullChannel` as a `replyChannel` header if that is missed
in the request message headers.
This way we cover both use-cases when we expect reply from the flow and
when it is used as a one-way scenario
* Improve a `HeaderEnricher` do not create a new `Message` if there are
no new headers to add/remove
* Remove a note from the `dsl.adoc` about now redundant `bridge()` after
`log()`
* Resolve TODO in the `.handle()` paragraph
* Restore anonymous class in the MessageHistoryIntegrationTests:
Mockito can't mock/spy lambdas because they are `final` classes
* Introduce `IntegrationFlowDefinition.logAndReply()` operator
* Fix logging message
Doc Polishing
Packages with `@Nullable` annotations need to have `@NonNulApi` at the package level.
There may be classes in these packages that have nullable arguments/returns that are
not currently marked as `@Nullable`. These will be fixed over time.
Also suppress JSR305 warnings when compiling tests.
* Polishing - PR Comments
* Fix memory leak in MHistorConfig & MBeanExpHelper
The `MessageHistoryConfigurer` is a `BeanPostProcessor` which keeps a
store of the `TrackableComponent`.
Something similar we have with the `MBeanExporterHelper` and its local
stores populated by the `postProcessBeforeInitialization()`
* Implement `DestructionAwareBeanPostProcessor` in the
`MessageHistoryConfigurer` and `MBeanExporterHelper` to remove destroyed
beans from their caches
**Cherry-pick to 5.0.x**
* * Fix concurrency and checkstyle
* Apply Java 8 style for collections iterations
JIRA: https://jira.spring.io/browse/INT-4513
The `IntegrationManagementConfigurer` keeps metrics beans in its local
stores.
When we add beans at runtime, they are not removed from those caches
after their removal
* Implement `DestructionAwareBeanPostProcessor` in the `IntegrationManagementConfigurer`
and clean up caches according provided bean type and its name
* Improve `ManualFlowTests` and `FtpTests` to be sure that
`IntegrationManagementConfigurer` caches are cleared after destroying
`IntegrationFlowRegistration`
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4514
`getBeansOfType()` with eager init does not currently return late registered singletons.
We should not be eagerly initializing here anyway.
**cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4510
Related to https://github.com/reactor/reactor-core/issues/1290
The `Flux.publish()` and subsequent `connect()` doesn't fuse a subscriber
for the hooks flow is interrupted (complete, or error, or disconnect).
In this case the `FluxMessageChannel.publishers` store is not cleared
from the finished publishers
* Add test-case to check the `FluxMessageChannel.publishers` store after
finishing the stream
* Add `hide()` operator with TODO to remove when an appropriate Reactor
version is ready
**Cherry-pick to 5.0.x**
https://build.spring.io/browse/INT-MASTER-1134
According the latest released reactor-core-3.2.0.M2, there is no yet
a `.onErrorContinue()` operator.
We need to stick with the `.errorStrategyContinue()` for time being
JIRA: https://jira.spring.io/browse/INT-4509
To avoid a re-usage of the `AbstractReplyProducingMessageHandler`,
the `IntegrationFlowDefinition` and `AbstractStandardMessageHandlerFactoryBean`
have a `static Set<>` to store already used producers and check it for
newly provided.
These stores are not cleaned when beans are destroyed leading to memory
leaks
* Implements a `DisposableBean` for the `AbstractStandardMessageHandlerFactoryBean`
to remove its `replyHandler` from the `referencedReplyProducers` on
`destroy()`
* Introduce a `IntegrationFlowDefinition.ReplyProducerCleaner` - an
`DestructionAwareBeanPostProcessor` to clean up removing `MessageProducer`
from the `IntegrationFlowDefinition.REFERENCED_REPLY_PRODUCERS`
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4507
* Add `RedisUtils` with the `isUnlinkAvailable()` to check the Redis
server version to be sure that `UNLINK` is available or not
* Use `RedisUtils.isUnlinkAvailable()` in the `RedisMessageStore` and
`RedisLockRegistry` when a removal functionality is performed
* Add `AbstractKeyValueMessageStore.doRemoveAll(Collection<Object> ids)`
for optimization
* Implement `doRemoveAll()` in the `RedisMessageStore` and
`GemfireMessageStore`
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4506
Capture the actual splitter result in the `FunctionIterator and close it if necessary.
**cherry-pick to 5.0.x**
Add Closeable to proxy in test; remove AutoCloseable check.
Closeable extends AutoCloseable.
Fix javadocs; test for AutoCloseable instead of Closeable
Polishing - PR comments; tighten up API.
A `CloseableIterator` is now an `AutoCloseable` with an overridden
`close()`` (no exception) to avoid lint problem.
* Polishing omissions, code style and `@author`
**Cherry-pick to 5.0.x**
* INT-4381: MessageSources refactoring
JIRA: https://jira.spring.io/browse/INT-4381
* Make all the out-of-the-box `MessageSource` implementations based
on the `AbstractMessageSource`
* Fix `JdbcPollingChannelAdapterIntegrationTests` for sporadic failure
because of `fixed-rate` for the poller
* Fix HeaderEnricherTests race condition
The `errorChannel()` expect an error in the `testErrorChannel` after
`1000` ms, but at the same time the `poller` in configured for the
`3000` ms.
* Increase all the timeouts for replies
* Decrease a `fixed-delay` on the `poller`
* Some other code style polishing for the `HeaderEnricherTests`
JIRA: https://jira.spring.io/browse/INT-4501
The call to the `IntegrationFlowBeanPostProcessor#setBeanFactory`
happens during BPP creation.
The introduced call to `beanFactory#getBean` triggers a lot of bean
creations.
For those beans not all `BPP`s are applied.
* Obtain a `flowContext` bean in lazy-load manner
**Cherry-pick to 5.0.x**
Since `IntegrationComponentSpec` is a `FactoryBean`, we need to care
about `Aware` and `init` & `destroy` hooks our selves or delegate
them through the `FactoryBean` wrapper
* Implement `InitializingBean` and `DisposableBean` on the
`IntegrationComponentSpec`
* Call the `Aware` hooks from the `IntegrationFlowBeanPostProcessor`
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4498
* Use `FileCopyUtils` instead of `StreamUtils` in test-cases when we deal
with `InputStream` s and files resources.
* Fix reflection-based tests with AOP to use an `ArrayList` access
instead of `LinkedList` since an optimization in SF:
6d6aa72e8f
**Cherry-pick to 5.0.x and 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4488
Since `PublisherAnnotationBeanPostProcessor` is quite expensive
(1.5x the CPU used by `MessagingAnnotationPostProcessor` in a simple
application)
* So not register a `PublisherAnnotationBeanPostProcessor` by default.
The `@EnablePublisher` has to be presented on the `@Configuration`
to allow the `@Publisher` AOP
* Change the `<int:annotation-config>` to require a new
`<int:enable-publisher>` sub-element for similar purpose - do not
register `PublisherAnnotationBeanPostProcessor` by default
JIRA: https://jira.spring.io/browse/INT-4452
This is pretty typical in practice to get a `groupTimeout` to be
evaluated to a negative value: some business decisions, sensitive
calculations and so on.
* Treat any non-positive `groupTimeout` as a signal to expire group
immediately without scheduling.
Only `null` is considered as a signal do nothing for the current message
* Polishing for some tests for better performance - saves some execution
time
JIRA: https://jira.spring.io/browse/INT-4489
Make `MessageHistoryConfigurer` as a `BeanPostProcessor` and apply
tracking logic to processed beans if it is already started.
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4487
Currently the `AbstractReplyProducingMessageHandler` applies advices
only in the `afterPropertiesSet()` phase.
When we use bean references for `MessageHandler`s in Java DSL, the
`.advice()` provided in the flow definition is not applied to the
`AbstractReplyProducingMessageHandler`.
* For consistency with the endpoint configured by the DSL definition,
override and reconfigure advices in the `AbstractReplyProducingMessageHandler`
bean reference during DSL parsing and processing.
Fix `TwitterSearchOutboundGatewayParserTests` for the proper assert
* Destroy RmiInboundGateway.RmiServiceExporter
The internal instance `RmiServiceExporter` of the `RmiInboundGateway`
has to be destroyed together with the outer instance to unbind `service`
from the RMI registry
* Perform some polishing for the `RmiInboundGateway` and optimize
a `AbstractInboundGatewayParser` for late channels binding
* * Polishing some tests
* Expose getters for channels on the `MessagingGatewaySupport`
* Fix RMI tests to use random port
JIRA: https://jira.spring.io/browse/INT-4485
The `IntegrationFlowBeanPostProcessor` performs extra bean registration
for the `IntegrationComponentSpec.get()` result.
Essentially it is going to be the same object in the end, but during
bean registration phase we end up with names conflict.
* Remove an explicit `registerComponent()` for the
`IntegrationComponentSpec.get()`
* Modify `CorrelationHandlerTests` for all possible usage for the
`MessageChannelSpec`, which is essentially a `FactoryBean`
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4486
The `SmartLifecycle.stop(Runnable callback)` must always call the
`callback` in the end independently of the internal state
* Revise all the `SmartLifecycle` implementations for the proper
`callback` handling
**Cherry-pick to 5.0.x and 4.3.x**
JIRA: https://jira.spring.io/browse/INT-4482
The outer try/catch sends an `ErrorMessage` for all exceptions; it should
only do so for `MessageConversionException`. Integration flow exceptions
will have been already handled by `MessageProducerSupport`.
Also, populate the raw message header consistently - previously it only
was populated for flow exceptions. Although the LEFE contains the raw
message, it should be in the `ErrorMessage` header for consistency.
**cherry-pick to 5.0.x, 4.3.x**
* Polishing - PR Comments
https://build.spring.io/browse/INT-MASTER-1058/
When we destroy manually registered `IntegrationFlow`, we need to
count with sub-flows and iterate all the dependant beans recursively
for full flow removal
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4476
When mapping outbound headers, if the `AmqpHeaders` `ID` and `Timestamp` headers
are not present, fall back to mapping the `MessageHeaders` variants (if present).
Also fix some PDF overflows.
JIRA: https://jira.spring.io/browse/INT-4474
* Populate proper `Integer.MIN_VALUE` phase for non-`PollingConsumer`s
in the `ConsumerEndpointFactoryBean`
**Cherry-pick to 5.0.x and 4.3.x**
* INT-4471: PubSubChannel: Add errorHandler warn
JIRA: https://jira.spring.io/browse/INT-4471
* When an `Executor` is not provided, log warn that the provided
`ErrorHandler` is ignored.
**Cherry-pick to 5.0.x and 4.3.x**
* * Polish warn message
JIRA: https://jira.spring.io/browse/INT-4478
When we use a `GenericHandler` and an incoming payload is a `Map`, we
copy it into both arguments into the `Object` for the payload
and `Map` for the headers.
This way we lose headers in the target lambda
* Check a size of arguments on the target lambda and don't set a
payload into the `Map` argument if we have more than 1 arguments
**Cherry-pick to 5.0.x**
JIRA: https://jira.spring.io/browse/INT-4477
When running multiple roles, it is useful to be able to determine the
role for a particular context, e.g. in an event.
* Docs
**cherry-pick to 5.0.x**
* Fix LockRegLeaderIn for interrupted Thread.sleep
https://build.spring.io/browse/INT-FATS5IC-517
If current thread is interrupted, the `Thread.sleep()` interrupts
immediately.
In the catch block of the main loop in the `LockRegistryLeaderInitiator`
we have such a dangerous `sleep()` and don't restart election in this
candidate any more
* Move `Thread.sleep()` to else after checking the current thread for
interrupted state
* Remove `LongRunningIntegrationTest` rule from the
`RedisLockRegistryLeaderInitiatorTests` since it now works much faster
after proper `busy-wait` handling
**Cherry-pick to master**
* Ignore interruption on the sleep i catch and move on with loop
JIRA: https://jira.spring.io/browse/INT-4473
Previously, dynamic registration of integration flows with components configured
with the same `id` would fail with duplicate bean names.
Add `useFlowIdAsPrefix()` to the registration builder to enable the option.
Then, in the BPP, check the flag before naming the beans.
**cherry-pick to 5.0.x**
* Polishing according PR comments
* Widen `flowNamePrefix` responsibility in the
`IntegrationFlowBeanPostProcessor` since we may have many other
components in the dynamic flow with the same id, not only consumer
endpoints
When we register `IntegrationFlow` s concurrently at runtime, we may
end up with the problem when we register the same object with the same
bean name, but in different places.
Or when we turn off bean overriding, we end up with the exception that
bean with the name already registered
* Wrap `IntegrationFlow` bean registration in the
`StandardIntegrationFlowContext` into the `Lock` when its bean name
is generating
* Make `StandardIntegrationFlowContext.registry` as `ConcurrentHashMap`
to avoid `ConcurrentModificationException` during `put()` and `remove()`
* Fix concurrency for beans registration with the generation names in
the `IntegrationFlowBeanPostProcessor` using an `IntegrationFlow` id
as a prefix for uniqueness.
**Cherry-pick to 5.0.x**
Fix generated bean name in the WebFluxDslTests
Use only single `Lock` in the `StandardIntegrationFlowContext`:
we don't need a fully blown `LockRegistry` there anymore since we have
only one synchronization block there and it is always around the same
type
* Add `What's New` note, and mention changes in the `dsl.adoc`
Minor doc polishing.
https://build.spring.io/browse/INT-MASTER-1042
The `verifyShutdownWithWait()` test uses extra thread for waiting for
the `TaskScheduler` to finish its tasks.
Also the test doesn't verify the actual behavior at all
* Move `awaitTermination()` to the assert
* Decrease `delay` for the message
* Assert the latch from the handler to be sure that message is scheduled
properly even if `destroy()` call, thanks to required
`waitForTasksToCompleteOnShutdown = true`
* INT-4397: Fix headers filtering for @Transformer
JIRA: https://jira.spring.io/browse/INT-4397
The `AbstractMessageProcessingTransformer` doesn't honor a configured
`notPropagatedHeaders` and copies all the request headers to the
message to return
* Add `setNotPropagatedHeaders()` into the `AbstractMessageProcessingTransformer`
and implement there a logic to filter headers, similar to what we have
in the `AbstractMessageProducingHandler`
* Overrider `updateNotPropagatedHeaders()` in the `MessageTransformingHandler`
to propagate `notPropagatedHeaders` to the `AbstractMessageProcessingTransformer`
delegate
* * Revert `final` for the `AbstractMessageProducingHandler.updateNotPropagatedHeaders()`
* Override `addNotPropagatedHeaders()` for the `MessageTransformingHandler()`
and populate `notPropagatedHeaders` into the target `AbstractMessageProcessingTransformer`
from there
* Also populate `notPropagatedHeaders` from the `AbstractMessageProcessingTransformer.doInit()`
* Implement a `AbstractIntegrationMessageBuilder.filterAndCopyHeadersIfAbsent()`
for a general logic to filter `notPropagatedHeaders` and copy the result
headers set into the target message if they are absent
* Use an new `filterAndCopyHeadersIfAbsent()` in the `AbstractMessageProducingHandler`
and `AbstractMessageProcessingTransformer`to avoid code block duplication
https://build.spring.io/browse/INT-MASTER-1038
When we don't provide an `output-processor` for the `<barrier>`
definition, the new logic in the `IntegrationNamespaceUtils.constructAdapter()`
ends up with the `null` injection into the `BarrierMessageHandler` ctor.
From here there is no guarantee which ctor will be selected:
```
BarrierMessageHandler(long timeout, MessageGroupProcessor outputProcessor)
...
BarrierMessageHandler(long timeout, CorrelationStrategy correlationStrategy)
```
From reflection perspective they both are equal and there is no predictable
outcome which is is going to be selected.
Looks like on Windows and OSX, the second (expected) is selected, but on
Linux it is the first one.
* Fix `IntegrationNamespaceUtils.injectCtorWithAdapter()` do not inject
`adapter` in to the target ctor if it is `null`.
This way the `BarrierMessageHandler(long timeout)` ctor is selected
without any ambiguity
* INT-4389: Default to SimpleSeqSizeReleaseStrategy
JIRA: https://jira.spring.io/browse/INT-4389
An `AbstractCorrelatingMessageHandler` fallback to the
`SimpleSequenceSizeReleaseStrategy` when `releaseStrategy` isn't
provided.
* Make `ReleaseStrategyFactoryBean` to fallback to the
`SimpleSequenceSizeReleaseStrategy` for consistency.
* * Fix `ResequencerParser` to fallback to the null `releaseStrategy`.
This way a subsequent `releasePartialSequences` will set a
`SequenceSizeReleaseStrategy` as a default one
* * Fix `BarrierMessageHandler` to populate a default `CorrelationStrategy`
* * More polishing to `BarrierMessageHandler`
JIRA: https://jira.spring.io/browse/INT-4466
When we schedule group for force complete in the
`AbstractCorrelatingMessageHandler`, we don't track a group `timestamp`
and its `lastModified` before the scheduled task.
This way, in the cluster environment, we may schedule several tasks
for different messages and the first started may release the group too
early.
Just because we extract a `MessageGroup` from the store already in the
task per se.
* Propagate the actual `timestamp` and `lastModified` from group before
scheduling task.
Compare these value with the actual group metadata in the
`processForceRelease()` before performing real `forceRelease()`.
This way we restore behavior before fixing memory leak, when we
propagated full `MessageGroup` to the scheduled task
* Implement `ResequencingMessageHandler.getComponentType()` for
consistency
* Remove unnecessary overhead with the `volatile` on many
`AbstractCorrelatingMessageHandler` properties, which hardly ever can be
changed at runtime
**Cherry-pick to 5.0.x and 4.3.x**