* 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**
https://build.spring.io/browse/INT-MASTER-999/
Since `BeanFactoryTypeConverterTests` and `CallerBlocksPolicyTests`
uses too long `Thread.sleep()` there is no guarantee that they are going
to be performed after expected 10 seconds
* Decrease `Thread.sleep()` in those tests
* Increase timeouts in the `RoundRobinDispatcherConcurrentTests` and
`ManualFlowTests`
* Fix `PollerAdviceTests` to re-use `TaskScheduler` from the ctx
instead of local, not closed instance
* Use `OnlyOnceTrigger` instead of local implementations
* Change the `primary` `Trigger` bean to the `PeriodicTrigger` as well.
The minimum interval for the `CronTrigger` is 1 seconds - it doesn't
matter for this test-case
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**
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**
JIRA: https://jira.spring.io/browse/INT-4441
Possible concurrent updates to `AbstractCorrelatingMessageHandler.groupIds` and
`expireGroupScheduledFutures`.
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-4390
Phase I: flow context/registration cycle
- extract interfaces
- rename implementations to `Standard...`
Phase II - dsl<->dsl.channel tangles
Move the channel specs to dsl.
Fix missing refactorings
(Not related to DSL) - rename core `event` package to `events`
- avoid collision with event module package
- fix tangle caused by `MessageGroupExpiredEvent`.
Phase III - dsl<->config.dsl
- move classes from config.dsl to dsl
(Not related to DSL) - fix many tangles caused by graph being a sub-package of support.management
- make `graph` a top-level package
(Not related to DSL) - move `IntegrationManagementConfigurer` from
`management` to `config` - tangle between core and management
* Polishing Copyrights, diamonds, some JavaDocs and What's New
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**
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**
JIRA: https://jira.spring.io/browse/INT-4392
Avoid the need for reflection on the `MicrometerMetricsCaptor`.
- move facade interfaces to a sub-package.
Remove deprecated `MicrometerMetricsFactory.
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-4392
JIRA: https://jira.spring.io/browse/INT-4391
JIRA: https://jira.spring.io/browse/INT-4393
Resolve class and leaf package tangles in:
- core (except DSL)
- file
- http
- move `StaticMessageHeaderAccessor` to root `integration` package
- move acknowledgment related classes to a new `acks` package
- move `MMIH` to `handler.support`, alongside argument resolvers, also `HandlerMethodArgumentResolversHolder`
- move `ErrorMessagePublisher` to `core`
- move `PatternMatchUtils` to `support.utils`
- move `MessageSourceManagement` to `support.management`
- remove direct reference to `MicrometerMetricsCapter` from `IntegrationManagementSupport`
- add new class `MetricsCaptorLoader`
- move `OperationsCallback` to inner interface in `RemoteFileOperations`
- move `HttpContextUtils` to `config`
* Simplify MetricsCaptor loading.
* Polishing
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**
JIRA: https://jira.spring.io/browse/INT-4394
Looks like Jackson has became much smarter and now it stores
the target type for the object, not returned interface.
We can't use Jackson annotations on the Framework classes and
we can't restrict the `messagingAwareMapper()` `ObjectMapper` just
to use fields for all the object passed through it.
As a compromise solution we shouldn't use
`Collections.unmodifiableList()` in the getter.
The copy of the internal collection is pretty enough to protect
our object from mutation.
**Cherry-pick to 4.3.x (excluding `build.gradle` change)**