Fixes: #9455
Issue link: https://github.com/spring-projects/spring-integration/issues/9455
* Add an `IntegrationKeepAlive` infrastructure bean to initiate a long-lived non-daemon thread
to keep application alive when it cannot be kept like that for various reason, but has to.
* Expose `spring.integration.keepAlive` global property to disable an `IntegrationKeepAlive` auto-startup
* Test and document the feature
Fixes: #9507
Issue link: https://github.com/spring-projects/spring-integration/issues/9507
* Deprecate `PythonScriptExecutor` in favor of `PolyglotScriptExecutor` with a `python` as language
* Add handling for `PolyglotWrapper` return type of the script evaluation
* Rework `DeriveLanguageFromExtensionTests.testParseLanguage()` to the `@ParameterizedTest`
Fixes: #9478
Issue link: https://github.com/spring-projects/spring-integration/issues/9478
Any `MessagingGatewaySupport` implementation does not register itself into a `SmartLifecycleRoleController`
because they don't call `super.onInit()` of the `AbstractEndpoint`
* Fix `MessagingGatewaySupport` for calling `super.onInit()` from its `onInit()`
* Verify `SmartLifecycleRoleController` registration in the `KafkaInboundGatewayTests`
* Remove out of use XML `group-id` attribute from Kafka channel adapter
and move it to the `channel` XSD as the place where it is really used
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
Fixes: #9436
Issue link: https://github.com/spring-projects/spring-integration/issues/9436
* Expose `IndexAccessor` configuration options on the `AbstractEvaluationContextFactoryBean`
and `SpelPropertyAccessorRegistrar`
* Expose `<index-accessors>` sub-element for the `<spel-property-accessors>`
* Adjust tests
* Document the feature, including recently added `JsonIndexAccessor`
Fixes: #9442
Issue link: https://github.com/spring-projects/spring-integration/issues/9442
When we register a `BeanDefinition`, its metadata is cached in the `DefaultListableBeanFactory.mergedBeanDefinitionHolders`
and it is not removed when we destroy bean.
This causes a memory leak with dynamic integration flows where even we destroy beans, their metadata is still cached.
This has more serious impact when random ids are used for dynamic integration flows.
* Rework `IntegrationFlowContext` logic to register singletons instead of `BeanDefinition`
* Adjust `IntegrationFlowBeanPostProcessor` logic to register singletons or `BeanDefinition`
according to the presence of `BeanDefinition` of the `IntegrationFlow` we are processing
* Introduce `ComponentSourceAware` to mimic a `BeanDefinition` metadata logic for bean source and its description.
This info helps a lot with exceptions where class in the `IntegrationFlow` might be fully from a Spring Integration package.
So, to give a clue what end-user code is related to the exception,
such a `ComponentSourceAware` is there to preserver and transfer "bean source"
* Implement `ComponentSourceAware` in the `IntegrationObjectSupport` since this is a central
place where we generate info for the Spring Integration exceptions
* Implement `ComponentSourceAware` in the `StandardIntegrationFlow` to propagate bean source info
down to its components for the mentioned `IntegrationObjectSupport` logic
* Introduce inner `StandardIntegrationFlowContext.IntegrationFlowComponentSourceAwareAdapter`
to be able to transfer "bean source" info from builder down to the target `IntegrationFlow` bean
Fixes: #9383
Issue link: https://github.com/spring-projects/spring-integration/issues/9383
* Polish `JsonPropertyAccessor[Tests]`
* Introduce `JsonIndexAccessor`
This commit introduces a `JsonIndexAccessor` as a complement to the
existing `JsonPropertyAccessor`.
When a `JsonIndexAccessor` is registered with the SpEL `EvaluationContext`,
JSON arrays can be consistently indexed via integer literals (e.g.,[1]) instead of string literals representing integers (e.g., ['1']).
Even if `Executors.newSingleThreadExecutor()` returns a `FinalizableDelegatedExecutorService`,
an instance is kept in the memory until JVM exists.
That may lead to memory leak since we have a lot of threads in memory.
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
Fixes: #9381
Currently, there is no way to know in one place what Control Bus commands are available and with what arguments
* Add `ControlBusCommandRegistry` infrastructure bean to gather control bus commands from beans and expose them for invocation
* Add `ControlBusController` to expose a `/control-bus` REST service against the mentioned `ControlBusCommandRegistry`
* Add `@EnableIntegrationManagement(loadControlBusCommands)` to be able to load all the Control Bus commands from the application context instead of on demand by default
* Deprecated existing SpEL(and Groovy)-based Control Bus functionality in favor of new, more manageable, logic
* Add `@DirtiesContext` to the `RecipientListRouterParserTests`
* Remove manual `context.start();` since it is started by the `@SpringJUnitConfig` anyway
Looks like `ApplicaitonContext.stop()` is note called on `close()`.
This might cause an `OutOfMemoryError` on the CI
* Use Spring context configuration for the test environment
Fixes: #9335
Spring Boot provides a `CompositeMeterRegistry` bean marked with a `@Primary`.
So, this one has to be autowired whenever we would like to deal with application
environment.
The `MicrometerNodeEnhancer` has a flaw to skip `MeterRegistry` injection if we have more than one `MeterRegistry` bean.
* Fix `MicrometerNodeEnhancer` logic to use `ObjectProvider.getIfUnique()` API
which is able to deal with the `primary` properly.
Otherwise, `null` as it was before
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
If we don't get access to `BeanFactory` in exclusive mode,
the `getBean(Class<?>)` may fail with a `BeanCurrentlyInCreationException`
when we register several `IntegrationFlow` instances in parallel
Fixes: #9259
The `Mono.toFuture()` does not propagate context to thread locals of the `CompletableFuture` consumer.
See `MonoToCompletableFuture`
* Fix `AbstractMessageProducingHandler` to convert reply `Mono` to `CompletableFuture` manually.
Use `doOnEach()` and set thread locals from the Reactor context manually around `replyFuture.complete()/completeExceptionally()`
* Add respective unit test into `WebFluxObservationPropagationTests` to ensure that same trace is used in downstream endpoints after WebFlux client reply
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
Fixes: #9260
The current `IntegrationManagementConfiguration.obtainObservationPatterns()` is to always have an `*` as a first
pattern in the final result.
Because of `HashSet` natural order.
This would lead to ignore all the patterns, especially those with negation
* Fix `IntegrationManagementConfiguration.obtainObservationPatterns()` logic to ignore regular
patterns if `*` is present.
Optimization wise.
* Always put `*` into the end of final array let negative patterns to do their job
* Modify `IntegrationGraphServerTests` & `WebFluxObservationPropagationTests`
test configurations to ensure that `*` pattern does not have a precedence over negative patterns.
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
The `Sinks.Many<Boolean> subscribedSignal` is a bit of overhead in the logic.
* Use `Mono.fromCallable(this.sink::currentSubscriberCount)` instead for `delaySubscription()`
when we perform `subscribeTo(Publisher)`
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
Fixes: #9191
Not all inbound protocol handlers convert header from native representation.
Sometimes they just come in as `byte[]`.
* Fix `MessageReceiverContext` to support `byte[]` for headers used in the observation,
e.g. `B3-*`, `traceparent` etc.
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
Fixes: #9215
* Instead of `share()` use `publish(1).refCount()` to prefetch only item from upstream.
* Also remove `publishOn(this.scheduler)` for upstream publishers in favor of opt-in on the consumer side.
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
Fixes: #9198
When observation is enabled on the `MessageChannel`, the message to send is converted to a `MutableMessage`.
In case of `ErrorMessage` this causes a loss of `originalMessage` and may lead to `ClassCastException`
in the target error handler.
* Check for `ErrorMessage` in the `AbstractMessageChannel.sendWithObservation()` and create a new one
as a copy of original request, but including observation headers before performing `sendInternal()`
* Modify `IntegrationObservabilityZipkinTests` to verify an observation with an `ErrorMessage` and its handler.
**Auto-cherry-pick to `6.3.x` & `6.2.x`**
* Move `whats-new` to `changes-6.2-6.3.adoc`
* Upgrade dependency to the latest (including Gradle)
* Move Spring dependencies to based on SF-6.2
* Fix some deprecations and incompatibility
Related to: #9110
* Make `IntegrationReactiveUtils.CONTEXT_SNAPSHOT_FACTORY` instance conditional on the `IntegrationReactiveUtils.isContextPropagationPresent`
to avoid class-not-found problem for the `io.micrometer.context.ContextSnapshot`
* Make `IntegrationReactiveUtils.captureReactorContext()` & `IntegrationReactiveUtils.setThreadLocalsFromReactorContext()`
conditional on the `isContextPropagationPresent`
**Auto-cherry-pick to `6.2.x`**
Fixes: #9110
* Move context propagation utilities to the `IntegrationReactiveUtils`
* Capture context into message header in the `IntegrationReactiveUtils.adaptSubscribableChannelToPublisher()`
before `sink.tryEmitNext()`
* Restore the context from message header in the `flatMap()` for `ReactiveStreamsConsumer.reactiveMessageHandler`
**Auto-cherry-pick to `6.2.x`**
Fixes: #9001
The `ObservationPropagationChannelInterceptor` does not propagate an observation properly.
And it fully cannot when the message channel is persistent.
* Deprecate `ObservationPropagationChannelInterceptor` in favor of enabled observation on the channel
and target `MessageHandler` which is a consumer of this channel.
* Remove tests with an `ObservationPropagationChannelInterceptor`
* Mention a correct behavior in the `metrics.adoc` and `ObservationPropagationChannelInterceptor` Javadocs
**Auto-cherry-pick to `6.2.x`**
Fixes: #8981
Sometime the simple `boolean failover` on the `MessageChannel` (default `true`)
is not enough to be sure that we can dispatch to the next handler or not.
Such a decision can be made using `ErrorMessageExceptionTypeRouter`, but that would
require an overhaul for the whole integration flow
* Introduce a simple `Predicate<Exception> failoverStrategy` into `UnicastingDispatcher`
and all its `MessageChannel` implementation consumers to allow to make a decision about next failover
according to a thrown exception from the current `MessageHandler`
* Expose `failoverStrategy` on the `DirectChannel`, `ExecutorChannel` & `PartitionedChannel`,
and add it into respective Java DSL specs
* Fix involved tests to rely on the `failoverStrategy` property from now on
* Document the new feature
Fixes: #7925
The `MessageHistory.write()` creates not only a new instance of the `MessageHistory`,
but also a new copy of the whole message.
This significantly impacts the performance when we have too many components to track
* Make `MessageHistory` as append-only container and create a new instance (plus message)
only on the first track when no prior history is present
* Change `WireTap`, `BroadcastingDispatcher`, `AbstractMessageRouter` and `AbstractMessageSplitter`
to use a new `AbstractIntegrationMessageBuilder.cloneMessageHistoryIfAny()` API for every branch a message
is produced.
Essentially, create a new message with copy of the message history to let that downstream sub-flow
have its own trace
* Modify failed unit tests for a new logic where message history header is not immutable anymore
* This also fixes an `AbstractMessageSplitter` for propagating its track into messages it emits
* * Do not clone message history header if only one consume in multi-publish
* Fix typos in docs
Fixes: #8950
The `IntegrationFlow.toReactivePublisher(true)` makes `PublisherIntegrationFlow`
to be stopped from the beginning and waiting for the `Publisher.subscribe()`.
However only `EndpointSpec` components are marked as `autoStartup(false)`.
The `MessageProducerSupport` is not included, therefore unexpected messages
are produced to the channel in the end of flow without subscribers.
* Check for `AbstractEndpoint` component type in the `PublisherIntegrationFlow`
and mark it as `setAutoStartup(false)`
* Ensure in a new `ReactiveStreamsTests.messageProducerIsNotStartedAutomatically()` test
that `MessageProducerSupport` is not started from the beginning,
but rather when we subscribe to the `Publisher` via `StepVerifier`
**Auto-cherry-pick to `6.2.x` & `6.1.x`**
There is no need to post-process the framework internal BPPs.
Therefore, mark `GatewayProxyInstantiationPostProcessor`, `GlobalChannelInterceptorProcessor`, `IntegrationFlowBeanPostProcessor`
and `BaseIntegrationFlowDefinition.ReplyProducerCleaner` as an `AopInfrastructureBean`.
This way they are not post-processed via AOP `BeanPostProcessor`
* Migrate `org.springframework.integration.aop` tests to JUnit 5
* Fix race condition in the `FluxMessageChannelTests.noMemoryLeakInFluxMessageChannelForVolatilePublishers()`
where `FluxMessageChannel.upstreamSubscriptions` is updated from a different thread
**Auto-cherry-pick to `6.2.x`**
Fixes: #8894
* Guard `this.messageStore` access in the `DelayHandler` with existing `this.lock`
to avoid `ConcurrentModificationException`
**Cherry-pick to `6.2.x`**
Fixes: #8893
Simplify the target flows logic for `ExpressionEvaluatingRequestHandlerAdvice.failureChannel`
when no exception is re-thrown and target flow would like to produce a reply.
Currently, there is need in extra logic like `.enrichHeaders(e -> e.replyChannelExpression("payload.failedMessage.headers[replyChannel]"))`
* Copy failed `Message` headers into an `ErrorMessage` before sending it into the `failureChannel` from the `ExpressionEvaluatingRequestHandlerAdvice`
Fixes: #8889
* Gather the current thread local state for the message into `IntegrationMessageHeaderAccessor.REACTOR_CONTEXT` header
before `this.sink.tryEmitNext(messageToEmit)`
* Restore thread locals for the current message in the `ReactiveStreamsConsumer.SubscriberDecorator` just before `this.delegate.onNext(messageToDeliver)`
**Cherry-pick to `6.2.x`**
The `ReactiveInboundChannelAdapterTests.testTimeSupplierConsistency()` subscribes a bit later than `@InboundChannelAdapter`
might have started to emit messages.
* Add `autoStartup = "false"` to the `timeEndpoint` and start in the test only when `StepVerifier` is subscribed
* Add `stop()` for both endpoints in the test configuration to avoid memory pollution with not processed messages in between tests