* GH-3635: Add Future<Void> & Mono<Void> to gateway
Fixes https://github.com/spring-projects/spring-integration/issues/3635
When `Future<Void>` & `Mono<Void>` is used as a messaging gateway return type,
the application hangs out on this barrier which may lead to the out of memory eventually
* Add support for the `Future<Void>` & `Mono<Void>` messaging gateway return type
and ensure an asynchronous call for the `gateway.send(Message)` operation and
its exception handling.
In case of successful call, the `Future` is fulfilled with `null` and `Mono` is completed as empty
* * Check for `void.class` as well in the `GatewayProxyFactoryBean.isVoidReturnType`
* * Allow `Future<Void>` as a reply type of the gateway request-reply operation
* * Fix Checkstyle violations
* * Resolve `System.err.println()` in the test code
* Add `Thread.currentThread.interrupt()` to the `InterruptedException` block in the test
* Fix new classes and packages tangles
* Move `MessagingAnnotationPostProcessor` and `MethodAnnotationPostProcessor` impls
out of the `config.annotation` package due to usage of the `FactoryBean` configs
* Move `GenericHandler` and `GenericTransformer` to the `core` package to break
a tangle with a `LambdaMessageProcessor`
* Clean up affected tests and docs
* * Fix Checkstyle violation for imports order
The `QueueChannel.receive()` may be fulfilled before
an observation is stopped in the `MessageHandler`
* Rework `IntegrationObservabilityZipkinTests` configuration to add
a `HandleMessageAdvice` to wait on the `CountDownLatch` before asserting spans
* Exclude an `adviceChain` attribute from the `ServiceActivatorAnnotationPostProcessor`
since an advice can be applied for the consumer endpoint, not the MH directly.
The `ConsumerEndpointFactoryBean` does the proper decision to apply advice onto MH
or just around its `handleMessage()` method
* Add some infrastructure for Observation
* Populate an `ObservationRegistry` bean from the `IntegrationManagementConfigurer`
into all the `IntegrationManagement` components
* Introduce `MessageReceiverContext` and `MessageSenderContext` for easier usage
in the target code
* Implement `Observation` handling in the `AbstractMessageHandler`
* Modify `ObservationPropagationChannelInterceptorTests` for new `MessageSenderContext`
* Use `BridgeHandler` to ensure that `Observation` is propagated and handled properly
* Verify that tags from the `AbstractMessageHandler` are preset on the consumer span
* * Add a `DocumentedObservation` infrastructure
* * Add `Timer` verification to the propagation test
* * Update to the latest Observation API
* * Add custom observation convention support for the `AbstractMessageHandler`
* Use more meaningful prefix for Spring Integration tags
* * Move singleton instance for `DefaultMessageReceiverObservationConvention`
into `DefaultMessageReceiverObservationConvention` per se as an `INSTANCE` constant
* Use `MeterRegistryAssert` in the `ObservationPropagationChannelInterceptorTests`
to verify meters emitted
* * And an integration test with Zipkin based on the `SampleTestRunner`
* Add Apache Camel support
* Implement `CamelMessageHandler` to perform send and send-n-reply
operations to the Apache Camel routes
* Fix `AbstractMessageProducingHandler` to handle async errors even if reply is
not expected
* * Narrow Camel dependency to `api`
Fixes https://github.com/spring-projects/spring-integration/pull/3660
* Change the `LambdaMessageProcessor` to invoke `Function`, `GenericHandler`,
`GenericSelector` & `GenericTransformer` explicitly without reflection.
This allows to avoid `--add-opens` for Java types to be used from reflections.
Plus this removes some overhead with native images.
And in general it is faster than reflection invocation.
The `ObjectToMapTransformerTests.testObjectToSpelMapTransformerWithCycle()`
causes a `StackOverflowError` according to the parent-child-parent cycle in the model under test.
This ends up with an error in the Gradle logs:
```
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 873
```
* Disable this test to avoid memory overhead and CPU time
to let Java determine stack overflow and avoid a build error
The `ObjectToMapTransformerParserTests.testObjectToSpelMapTransformerWithCycle()`
causes a `StackOverflowError` according to the parent-child-parent cycle in the model under test.
This ends up with an error in the Gradle logs:
```
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at s\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 873
```
* Disable this test to avoid memory overhead and CPU time
to let Java to determine stack overflow and avoid a build error
* Add more proxy hints for interfaces we use in the framework code
* Implement `BeanRegistrationExcludeFilter` to exlude `BeanFactoryPostProcessor` beans
* Remove `AotDetector.useGeneratedArtifacts()` from those `BFPP`s
* Rework infra logic onto IntegrationProperties
The `Properties` bean has been deprecated since `5.5`
* Register a default `integrationGlobalProperties` as a `IntegrationProperties`
* Fix respective usages from the `Properties`
* * Remove unused constant from the `IntegrationContextUtils`
* * Fix language in the `whats-new.adoc`
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
* Add `@Reflective` to methods of `Pausable` and `ManageableLifecycle`
to give them access from Control Bus which uses SpEL invocation engine -
reflection, essentially
* Add proxy hint for the `RequestReplyExchanger`, which is used for
`gateway()` definition in Java DSL
* GH-3828: Initial Spring AOT support
Fixes https://github.com/spring-projects/spring-integration/issues/3828
* Provide an infrastructure based on a new Spring AOT engine in the latest Spring Framework
* Introduce `RuntimeHintsRegistrar` impls into modules which require some reflection,
resources or proxies and serialization available in the native image
* Mark some framework method with the `@Reflective` to make their reflection
info available in the native image, for example for SpEL or JMX invocations
* Add a `GatewayProxyBeanRegistrationAotProcessor` to register proxy interfaces
info for messaging gateways (either instance of the `GatewayProxyFactoryBean`)
* Rework `ConverterRegistrar` to not use a `beanFactory.getBeansWithAnnotation()`
since it is not available after AOT phase.
Instead, register an intermediate `IntegrationConverterRegistration` bean definition
from the `IntegrationConverterInitializer`
* Refactor `GlobalChannelInterceptorInitializer` a bit according to a new logic in the
`IntegrationConverterInitializer`
* Remove `JsonNodeWrapperToJsonNodeConverter` bean registration from the
`DefaultConfiguringBeanFactoryPostProcessor` - it is added by the `ConverterRegistrar`
into the target `ConversionService`
* Fix `ParentContextTests` respectively a `JsonNodeWrapperToJsonNodeConverter` bean removal
* Refactor `XsltPayloadTransformer` to not load a `ServletContextResource`, but just use its
name for the `xslResource` condition
* * Rework AOT support according latest changes and requirements
* Remove `@Bean` reflection since it is not needed any more
* Add `AotDetector.useGeneratedArtifacts()` condition to not register beans
one more time at runtime after AOT build phase
* Fix deprecation in the WebFlux test from the latest SF
The `GenericJackson2JsonRedisSerializer` now resolves the target type
before calling `ObjectMapper.readValue()` causing a `ClassCast` in the
`StdNodeBasedDeserializer.deserializeWithType()`
* Override `MessageJacksonDeserializer.deserializeWithType()` with delegating
to the plain `deserialize()` ignoring the `TypeDeserializer`
Related to https://github.com/spring-projects/spring-data-redis/issues/2322
* GH-3844: Rework messaging annotation with @Bean
Fixes https://github.com/spring-projects/spring-integration/issues/3844
* Make `MessagingAnnotationPostProcessor` as a `BeanDefinitionRegistryPostProcessor`
to process bean definitions as early as possible and register respective messaging
components at that early phase
* Make bean definitions parsing logic optional for AOT and native mode since beans
have bean parsed during AOT building phase
* Introduce a `BeanDefinitionPropertiesMapper` for easier mapping
of the annotation attributes to the target `BeanDefinition`
* Remove `@Bean`-related logic from method parsing process
* Change the logic for `@Bean`-based endpoint bean names:
since we don't deal with methods on the bean definition phase, then method name
does not make sense.
It even may mislead if we `@Bean` name is based on a method by default, so we end up
with duplicated word in the target endpoint bean name.
Now we don't
* Fix `configuration.adoc` respectively for a new endpoint bean name logic
* In the end the new logic in the `AbstractMethodAnnotationPostProcessor`
is similar to XML parsers: we feed annotation attributes to the
`AbstractStandardMessageHandlerFactoryBean` impls
* * Fix language in docs and exception message
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`**
* Initial support for Micrometer Observation
* Add respective Observation dependencies
* Refactor an `AbstractMessageHandler` logic for potential Observation hooks
* Introduce an `ObservationPropagationChannelInterceptor` to propagate
an `Observation` from one thread to another through message channels
* Adds an example of propagation
* Fixed the user code and receiving spans
* * Clean up for Tracing unit test
* Make `micrometer-observation` as an `api` dep - non-optional for direct API usage
Co-authored-by: Marcin Grzejszczak <marcin@grzejszczak.pl>
* Fix deprecations around ListenableFuture
SF has deprecated a `ListenableFuture` and API around it
* Migrate to `CompletableFuture` everywhere a `ListenableFuture` has been used
* Suppress a deprecation for `ListenableFuture` keeping the functionality until the next version
* Resolve deprecations nad removals from the latest Spring for Apache Kafka
* Fix documentation for the `ListenableFuture` in favor of `CompletableFuture`
NOTE: the AMQP module is left as is until `ListenableFuture` deprecation is resolved in Spring AMQP
* * Restore some `ListenableFuture` test for messaging gateway
Spring for Apache Kafka does not produce `ListenableFuture` anymore.
* Rework `KafkaProducerMessageHandler` to deal with the `CompletableFuture` from now on
* Add support for `CompletableFuture` replies handling into `AbstractMessageProducingHandler`
* Remove redundant cast in the `DispatcherHasNoSubscribersTests`
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`**
* Remove previously deprecated methods with typos from the `ClassUtils`
* Optimize `ClassUtils` logic via `KotlinDetector.isKotlinPresent()` condition
* Resolve deprecation warnings in the `JmsOutboundGateway` around `TaskScheduler`
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`**
* Mostly changes are related to the `TaskScheduler` and `Trigger` APIs
* Migrate to `micrometer-tracing` dependency
* Rework `SocketTestUtils` to use a `InetAddress.getLocalHost()`
for more stability and performance on Windows
* Fix docs for new `PeriodicTrigger` API
The `DirectChannel` doesn't check a result of the `getIntegrationProperty()`.
This may cause NPE problem with unconditional `setMaxSubscribers(int)` call.
* Check `Integer max` for `null` before propagating to the `setMaxSubscribers()`
Fixes https://github.com/spring-projects/spring-integration/issues/3623
* `IntegrationFlow` refactoring
* Apply several code style improvements and good practices
* Code style: no empty lines for methods javadocs
* make deprecated implementation reuse actual one instead of the copy-paste approach
* add whats-new comments
* Fix whats-new page according to standards
* Upgrade Spring dependencies to the latest SNAPSHOTs
* Fix tests to verify against stack traces: the message
of the `NestedRuntimeException` does not include the nested exception information.
Related to https://github.com/spring-projects/spring-framework/issues/25162
* Fix `JdbcMessageStore` and `DefaultLockRepository` to rely on the `DataIntegrityViolationException`
instead of only its `DuplicateKeyException` extension.
This is the current behavior of the SQL errors translation
* Disable `WebFluxDslTests.testValidation()` - doesn't subscribe to the reply somehow...
* Refine `SimplePool.PoolSemaphore.reducePermits()`
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`**
* GH-3797: Improve batch processing in the framework
Fixes https://github.com/spring-projects/spring-integration/issues/3797
* Handle `Message` items of the `Iterable` payload properly in the `JdbcMessageHandler`.
Otherwise, they've been wrapped into an extra `Message`
* Produce a single message with a `Collection<Message<?>>` payload in the `AggregatingMessageHandler`
when the `getOutputProcessor()` is not an instance of `SimpleMessageGroupProcessor`
* Mention these changes in docs
* Point to the error handling sample from docs
* * Fix language in docs
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
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`**
* Add recommended JVM args to the Gradle module for HZ performance
* Move `IdempotentReceiverIntegrationTests` from JMX module to HZ for consistency
* Remove component scan from the `HazelcastIntegrationOutboundTestConfiguration` - redundant
* Use `HazelcastInstance.shutdown()` during normal context lifecycle.
The `@AfterClass` may happen early, so the `stop()` of the channel adapters may fail with
an exception that HZ is not available causing the `LifecycleProcessor` to wait for 30 seconds
on the lifecycle barrier
* Wrap `AbstractEndpoint.doStop()` call into `try..catch` to log error instead of re-throwing
to avoid the mentioned above 30 secs delay of the application context stop
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`**
The `Thread.sleep(1000);` doesn't give a good async barrier to rely on
in the subsequent verification logic.
Use `await().until()` instead for several attempts until a condition is fulfilled
ot 10 seconds timeout is exhausted.
Also decrease `reapDelay` to `500` for better test suite performance
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`**
Fixes https://github.com/spring-projects/spring-integration/issues/3592
* Configure XML parser & Java DSL for Scatter-Gather, based on the
`RecipientListRouter` to set an `applySequence` to `true` by default.
This will make a `gatherer` part to fully rely on the default correlation
strategies
* 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