* GH-3945: Fix `not eligible for getting processed`
Fixes https://github.com/spring-projects/spring-integration/issues/3945
The `IntegrationManagementConfiguration` produces an `IntegrationManagementConfigurer` which is a `BeanPostProcessor`.
According to Spring recommendation this kind of infrastructure beans must be declared as `static`.
Due to an `implements ImportAware, EnvironmentAware` nature of the `IntegrationManagementConfiguration`,
we cannot use `static @Bean` method.
But since the `IntegrationManagementConfiguration` is not involved in any bean post-processing,
it is safe to follow recommendation and mark it as a `@Role(BeanDefinition.ROLE_INFRASTRUCTURE)`.
* Fix `MessagePublishingInterceptor` to initialize `MessagingTemplate` and `DestinationResolver` lazily
* Fix `AbstractMethodAnnotationPostProcessor` to initialize `DestinationResolver` lazily
**Cherry-pick to `5.5.x`**
* Use `getChannelResolver()` internally in the `AbstractMethodAnnotationPostProcessor`
instead of direct property access which might not be initialized yet
* Use a plain `boolean` for `templateInitialized` in the `MessagePublishingInterceptor`
to avoid skips in other thread where and move on with still not initialized properties
* Remove unused import
* Fix `this.` prefix for `beanFactory` property reference
# Conflicts:
# spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java
* Fix double start for `AbstractEndpoint`
When we use POJO methods in the `IntegrationFlowAdapter`,
the `IntegrationFlowAdapter` is set as a `target` for the `MessagingMethodInvokerHelper`.
When endpoint is started by the application context, such a `start()` is propagated
down to the `MessagingMethodInvokerHelper`.
And in our case back into an `IntegrationFlowAdapter` instance.
This one, in turn, starts its `IntegrationFlow` internally which leads to the
start of the mentioned endpoint in the beginning.
Therefore, we cause a recursive `start()` call on this endpoint from itself.
The `running` flag is set when we are already done with the `doStart()` logic.
Therefore a recursive `start()` call leads to two concurrent polling tasks
in the `AbstractPollingEndpoint`.
* Check also for the `active` flag in the `AbstractEndpoint.start()`
and reset it in case of exception in the `doStart()`
**Cherry-pick to `5.5.x`**
* * Change assert for message timestamps to `isCloseTo()` with percentage
* * Change `catch` in the `AbstractEndpoint.start()` to `RuntimeException`:
the `doStart()` cannot throw unchecked exceptions by definition
* * Fix imports in `AbstractEndpoint`
Fixes https://github.com/spring-projects/spring-integration/issues/3875
The class `static` variables and initialization block are performed on first class access.
* Add "fake" `ClassUtils.resolvePrimitiveType(Integer.class)` call to the `IntegrationRegistrar`
to trigger `ClassUtils` initialization with the current Spring `ClassLoader`
**Cherry-pick to `5.5.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3843
The `MessageHistory.write()` is missing the `ErrorMessage.originalMessage`
on creating a new `ErrorMessage` with message history header
* Reuse an `ErrorMessage.originalMessage` for newly created `ErrorMessage`
after populating the message history header
**Cherry-pick to `5.5.x`**
The `ClassUtils.isKotlinFaction0()` and `ClassUtils.isKotlinFaction1()`
are wrong names.
* Deprecate `ClassUtils.isKotlinFaction0()` and `ClassUtils.isKotlinFaction1()`
in favor of newly introduced `isKotlinFunction0()` and `isKotlinFunction1()`
**Cherry-pick to `main`**
Fixes https://github.com/spring-projects/spring-integration/issues/3826
By default, the `SimplePool` is used with an `Integer.MAX_VALUE` pool size.
There is a performance degradation in the `setPoolSize()` when we try to
decrease the pool size: the `while` for `permits.tryAcquire()` is too long
close to the current `Integer.MAX_VALUE` pool size
* Revise the logic in the `setPoolSize()` to use `Semaphore.reducePermits()`
instead of the loop.
* Change the calculation for a new pool size for the current pool state:
or it is a size of a new request, or iti s equal to the `inUse.size()`.
It will be reduced on subsequent `releaseItem()` calls
* Reduce the number of `available` according a new pool size based on the `inUse`.
So, if `inUse > newPoolSize`, the `available` is cleared.
Otherewise, it is reduced to the number which would give `newPoolSize` together
with the `inUse` size
**Cherry-pick to `5.5.x`**
Related to https://stackoverflow.com/questions/72305387/spring-integration-delayer-starts-sending-null-message-payloads-when-switched
In some async use-cases (e.g. `DelayHandler`), the context classloader
might be different for the data to be deserialized from message store.
* Fix `JdbcMessageStore` to populate a bean `ClassLoader` into default
`AllowListDeserializingConverter` from the application context.
The provided `Deserializer` must ensure such a `ClassLoader` itself
* Add warning message to the `LambdaMessageProcessor` when converter
returns `null` for the payload it cannot convert to expected type.
Cannot be raised as error since some applications may already rely
on the `null` conversion result in their method arguments
**Cherry-pick to `5.5.x`**
The `FluxAggregatorMessageHandlerTests.testWindowTimespan()`
relies on the time-based window function of `100` millis.
Looks like a delay of `Thread.sleep(20)` may cause a resources race
condition and window is released only with one item.
* Disable `testWindowTimespan()` since there is no guarantee with what
timing settings it is going to work stably
**Cherry-pick to `5.5.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3794
* Replace hard reference to message group with its `id` in the
`AbstractCorrelatingMessageHandler.removeEmptyGroupAfterTimeout()`
* Replace hard reference to message with its `id` in the
`DelayHandler.rescheduleAt()`
**Cherry-pick to `5.5.x`**
* GH-3785: Close stream for persistent collection
Fixes https://github.com/spring-projects/spring-integration/issues/3785
* Fix `CollectionArgumentResolver` and `PayloadsArgumentResolver` to
close the `Stream` of message after its usage
* Rework `AbstractKeyValueMessageStore.removeMessagesFromGroup()`
to iterate input collection of messages not its stream to avoid
the mentioned problem
**Cherry-pick to `5.5.x`**
* * Add `JdbcMessageStoreTests.testMessageGroupStreamNoConnectionPoolLeak()`
to ensure that no leaks in the connection pool anymore.
* Improve `MessageGroupStore.streamMessagesForGroup()` JavaDocs about
requirements to close the `Stream` from persistent message store impls
Fixes https://github.com/spring-projects/spring-integration/issues/3765
The `DefaultMethodInvokingMethodInterceptor` has several strategies
for `default` method invocations in the messaging gateway.
One of them is based on the `Lookup` constructor which causes
a `WARNING: An illegal reflective access operation has occurred`.
This can be done lazily when there is no `MethodHandles.privateLookupIn`
in Java version used for the project.
* Fix `OPEN` enum value for the `Constructor<Lookup>` to be resolved in
a lazy manner via `Supplier` and `boolean` flag
**Cherry-pick to `5.5.x`**
Fixes https://github.com/spring-projects/spring-integration/issues/3734
The `MessageHistory` is not in the trusted packages of the `DefaultKafkaHeaderMapper`
therefore it fails when `MessageHistory.read()` is performed.
* Configure default `DefaultKafkaHeaderMapper` in the `SubscribableKafkaChannel`,
`KafkaInboundGateway`, `KafkaMessageDrivenChannelAdapter` and `KafkaMessageSource`
to also trust packages exposed via `JacksonJsonUtils.DEFAULT_TRUSTED_PACKAGES`
which include a `MessageHistory`, too.
* Verify in some integration Kafka tests to be sure that `MessageHistory` is
deserialized properly in the transferred headers
* Rework some tests to use `@EmbeddedKafka` instead of `@BeforeAll/@AfterAll`
**Cherry-pick to `5.5.x`**
The `Flux.takeWhile()` only works if there is data in the `Publisher`
to consume.
We still need to be able to cancel subscription and stop producing even if
there is no data at the moment.
* Change `takeWhile()` to the `doOnSubscribe()` and store `subscription`
in the `volatile` property of the `MessageProducerSupport`
* Cancel such a subscription in the `doStop()` impl
* Propagate `doStop()` to super in the `ZeroMqMessageProducer`
which is only one reactive channel adapter overriding `doStop()`
* Verify in the `ReactiveMessageProducerTests` that subscription is cancelled
for delayed data in the `Publisher`
**Cherry-pick to `5.5.x`**
Turns out Eclipse Kotlin plugin is not perfect at the moment,
and it causes some code parsing problems in the editor.
* Move Kotlin annotation to Java to mitigate normal source code flow:
Java to Kotlin, not opposite
* Add missed factories, introduced recently into Java DSL
* Add `@IntegrationDsl` - a Kotlin-specific `@DslMarker` annotation
to mark classes (including Java) which are used in Kotlin DSL as a builder pattern.
This way the scope of the builder is honored and IDE does not suggest functions from
higher lambda for builder
* Fix `element-list` reference for Dokka plugin configuration from the respective module
* GH-3694: Resolve circular dep in PublisherAnnBPP
Fixes https://github.com/spring-projects/spring-integration/issues/3694
* Move check for `PublisherAnnotationBeanPostProcessor` bean into the
`SmartInitializingSingleton.afterSingletonsInstantiated()` to break a circular dependency revealed
in the `InitializingBean.afterPropertiesSet()`
* * Fix unused import
Rework the logic around `ManagedList` in the `DefaultConfiguringBeanFactoryPostProcessor`
when it registers a `IntegrationContextUtils.MESSAGE_HANDLER_FACTORY_BEAN_NAME` and
`IntegrationContextUtils.LIST_MESSAGE_HANDLER_FACTORY_BEAN_NAME` into a dedicated
`MessageHandlerMethodFactoryCreatingFactoryBean` with pure Java code instead of
`BeanDefinition` burden
* Deprecate `IntegrationContextUtils.DISPOSABLES_BEAN_NAME` constant for
already removed internal bean
* Align JVM args for Gradle with Java 17 on the `6.0` branch
* Remove `Disposables` since it is a package protected therefore could not be used outside
* Remove the logic relevant ot the `Disposables` in the `MessagingAnnotationPostProcessor` logic
* Replace a `registerSingleton()` and `initializeBean()` with the proper `registerBeanDefinition()`
and `getBean()` usage.
This way bean are going to be destroyed properly
* Remove `MessagingAnnotationPostProcessorChannelCreationTests` since its mocking logic is too vague
and really covered with many other real tests.
The `MessagingAnnotationPostProcessor` registers a `Disposables` unconditionally.
The `afterPropertiesSet()` maybe called several times, so `IntegrationContextUtils.DISPOSABLES_BEAN_NAME`
registration has to be idempotent.
* Add `if (!this.beanFactory.containsBeanDefinition(IntegrationContextUtils.DISPOSABLES_BEAN_NAME))`
before trying to register `Disposables` bean
The `AnnotationGatewayProxyFactoryBean` can be configured via setters
and via annotation in the provided interface.
* Override `setProxyDefaultMethods()` to `true` only if annotation explicitly
provides `true`
Turns out Java does cast for the method reference argument before really calling
a delegating method.
* Revert cast method references (`((ApplicationContextAware) this.handler)::setApplicationContext`)
back to lambdas - `context -> ((ApplicationContextAware) this.handler).setApplicationContext(this.applicationContext)`
This way the cast is deferred until the lambda is called.
* Make a `DefaultConfiguringBeanFactoryPostProcessor` as a `BeanDefinitionRegistryPostProcessor`
to let it be processed properly in Spring AOT
* Register `DefaultConfiguringBeanFactoryPostProcessor` as a `BeanDefinition.ROLE_INFRASTRUCTURE`,
so it is removed in Spring AOT after processing and writing target bean definitions
The `LambdaMessageProcessor` and `MethodInvokingMessageSource`
call `method.setAccessible(true)` unconditionally.
* Use `ReflectionUtils.makeAccessible()` for some optimization
* Remove `Content is not allowed in prolog` from the `JaxbMarshallingIntegrationTests`
since it is locale dependant and not relevant for the unit test logic
* Add `toReactivePublisher(autoStartOnSubscribe)`
The `IntegrationFlowBuilder.toReactivePublisher()` returns a `Publisher<Message<?>>`
which may be subscribed somewhere late in the application logic, e.g.
when WebSocket (or RSocket) subscription is initiated by the external client.
In between application context startup and that subscription moment, the `IntegrationFlow`
must not try to produce messages since there is nothing to consumer them from the
`Publisher<Message<?>>` side.
One of the way is to have a source endpoint not started automatically and control its
lifecycle from the point fo reactive subscription
* Introduce an `IntegrationFlowBuilder.toReactivePublisher(boolean autoStartOnSubscribe)`
to let the framework do a job for an `IntegrationFlow` lifecycle control.
This way end-user doesn't need to know autowire a starting endpoint and use `doOnSubscribe()`
and similar callbacks
* Change `ConsumerEndpointFactoryBean` log message about a `FixedSubscriberChannel`
to `INFO` since an `autoStartup = false` really does not have any effect and there is nothing
for end-user to worry about.
The `IntegrationFlow` knows nothing about each endpoint internals and cannot control which
mark as `autoStartup = false` and which not
* Fix languge in JavaDocs
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
Fixes https://github.com/spring-projects/spring-integration/issues/3656
* Move `JavaUtils` from `util` package to the root one to break any possible
tangling to/from other packages.
* Deprecate an existing `JavaUtils` for backward compatibility
* Remove `@IntegrationConverter` from the `JsonNodeWrapperToJsonNodeConverter`
and register it manually in the `ConverterRegistrar`.
The bean registration for the `JsonNodeWrapperToJsonNodeConverter` must be removed
in the next `6.0`
* Remove usage of `IntegrationContextUtils` from the `support` package
* GH-3653: Improve DSL parsing performance
Fixes https://github.com/spring-projects/spring-integration/issues/3653
* Refactor `IntegrationFlowBeanPostProcessor` to perform `beanFactory.getBeansOfType()`
as less as possible
* Implement a `NamedComponent` on the `StandardIntegrationFlow` for better
bean scanning performance in the `IntegrationFlowBeanPostProcessor`
* * Skip `NamedComponent` from bean scanning if `beanName == null`
Resolves https://github.com/spring-projects/spring-integration/issues/3648
When configuring a gateway proxy with XML, but specifying the payload expression
on the method `@Gateway` annotation, the expression was ignored, even though it
had been parsed.
`@Payload` worked.
With this change, if both `@Payload` and `@Gateway` are defined on a gateway method,
`@Gateway.payloadExpression` wins.
* Fix doc links.
* Improve JavaDocs for `BaseIntegrationFlowDefinition` with renaming `payloadType`
param to `expectedType` since it can also be as a `Message.class`, not only type
for the payload.
* Add JavaDoc for `LambdaMessageProcessor` ctor
Fixes https://github.com/spring-projects/spring-integration/issues/3643
The `ImportBeanDefinitionRegistrar` register its bean definition in the early phase.
It causes a problem with Spring Boot when an explicit `@EnableIntegrationManagement`
is declared: the `MeterRegistry` is provided later on via auto-configuration
and `MicrometerMetricsCaptor` has no knowledge about `MeterRegistry` at the
`ImportBeanDefinitionRegistrar` phase.
* Reworks `MicrometerMetricsCaptorRegistrar` to the `MicrometerMetricsCaptorConfiguration`
and use special conditional `MicrometerMetricsCaptorImportSelector` for that
`@EnableIntegrationManagement`.
This way a `MicrometerMetricsCaptor` `@Bean` consults `ObjectProvider<MeterRegistry>`
on its creating time and returns `null` if no `MeterRegistry` beans at all.
* Fix Kotlin deprecation warning in the test
* Replace wrong `IntervalTrigger` mentioning in the docs to the proper `PeriodicTrigger`
* Fix code snippet in the `channel-adapter.adoc`