Commit Graph

11263 Commits

Author SHA1 Message Date
Anton Gabov
46e684ef32 RedisLockRegistry: Don't expire not acquired lock
Fix race condition, when methods `RedisLockRegistry#expireUnusedOlderThan` and `RedisLockRegistry#obtain` are executed successively. 

It's possible to delete the lock from `RedisLockRegistry#expireUnusedOlderThan` method, when lock is created but is not acquired (`RedisLock#getLockedAt = 0`)
It can lead to the situation, when `RedisLockRegistry#obtain` returns multiple locks with the same redis-key, which shouldn't happen at all.

* Skip locks from expiration when their `lockedAt == 0` - new, not acquired yet.

**Cherry-pick to `6.0.x` & `5.5.x`**
2023-03-15 11:18:48 -04:00
Artem Bilan
2adf33467c Some LockRegistryLeaderInitiator improvements (#8570)
* Some `LockRegistryLeaderInitiator` improvements

It is better to not go to the target lock provider at all
if the current thread is already interrupted.

* Check for the `Thread.currentThread().isInterrupted()` in the `while` loop
and `restartSelectorBecauseOfError()` immediately without checking for a lock
* Fix some other simple typos in the `LockRegistryLeaderInitiator`

**Cherry-pick to `6.0.x`**

* * Introduce a `LeaderSelector.yielding` flag
to revoke leader smoothly.
Turns out just canceling the `Future` may lead to a broken lock
where we cannot unlock it because the target lock repository may not work
with interrupted threads.
This way a new leader must wait until the lock is expired in the store
2023-03-15 10:10:51 -04:00
Chris Bono
5c96c0ded0 Reduce instance supplier use to appease AOT
* Remove the use of instance suppliers on bean definitions
that are processed during the AOT phase.

* The remaining areas that use instance suppliers do so
at runtime and do not use reflection, but instead
are passed the configured bean to register.

See https://github.com/spring-cloud/spring-cloud-stream/issues/2655

**Cherry-pick to `6.0.x`**
2023-03-02 19:01:21 -05:00
Artem Bilan
d9f3821b9b GH-8562: Fix streaming source for remote calls (#8564)
* GH-8562: Fix streaming source for remote calls

Fixes https://github.com/spring-projects/spring-integration/issues/8562

The `AbstractRemoteFileStreamingMessageSource.doReceive()` takes files first from a `toBeReceived` queue.
When `AbstractRemoteFileStreamingMessageSource.remoteFileToMessage()` fails to fetch the file content
because of interim connection issue, we reset this file from a filter and rethrow an exception.
The next `receive()` call will just go ahead to the next entry in the `toBeReceived` queue, but the
file we have just failed for will be retried only on the next list call to the remove directory.
This essentially breaks a possible in-order target application logic.

* Introduce `AbstractRemoteFileStreamingMessageSource.strictOrder` option to clear the `toBeReceived` queue
 when we fail in the `remoteFileToMessage()`, so the next `receive()`
 call would re-fetch files from remote dir, because the filter has been reset for those files.
* Fix `AbstractFileInfo.toString()` to not perform remote calls when we just log this file.
For example, we reset the file for connection failure and log the message about it,
but it fails again because we request `size` of the file which may require a remote connection.

**Cherry-pick to `6.0.x` & `5.5.x`**

* * Revert `AbstractFileInfo` changes
* Override `toString()` in `SmbFileInfo` instead -
exactly the place where connection is used to obtain
file attributes like `size` or `lastModified`
2023-02-28 16:43:48 -05:00
abilan
36c05ff3e6 Fix new Sonar smells
**Cherry-pick to `6.0.x`**
2023-02-22 12:39:39 -05:00
Spring Builds
ab32591012 [artifactory-release] Next development version 2023-02-21 19:31:05 +00:00
Spring Builds
7592c64073 [artifactory-release] Release version 6.0.3 2023-02-21 19:31:02 +00:00
abilan
ee5ea036cc Fix deprecations from upstream dependencies 2023-02-21 13:47:15 -05:00
abilan
a8dd9188c1 Upgrade dependencies; prepare for release 2023-02-21 13:14:40 -05:00
Artem Bilan
ee2b6b4098 Fix MQTT Inbound readyToSubscribeOnStart logic (#8557)
We cannot always reset `readyToSubscribeOnStart` to `false` in the `stop()`
since we may be connected to `ClientManager` and have `cleanStart` option,
so we `unsubscribe()` in the stop and then when we start there is no way to subscribe back

* Reset `readyToSubscribeOnStart` in the `AbstractMqttMessageDrivenChannelAdapter.doStop()`
only if we don't unsubscribe for a `cleanSession` reason.
* Also reset it in the `connectionLost`, so next `connectComplete` will take care about subscription
or `readyToSubscribeOnStart` state change
* Use `isActive()` instead of `isRunning()` in the `connectComplete()` since there is a race
condition when connection is established but `doStart()` has not returned yet, but already passed
`if (this.readyToSubscribeOnStart)` line
2023-02-21 12:57:30 -05:00
Artem Bilan
ac577e9ef7 Optional io.micrometer:context-propagation (#8556)
For better performance by default it is better to not pull
a `io.micrometer:context-propagation` a hard dependency.

* Remove `io.micrometer:context-propagation` dependency management
* It is pulled transitively by the `io.micrometer:micrometer-tracing-integration-test` in test scope
* Rework all the `ContextSnapshot` usage in the reactive code to respective recommended `handle()` API in `Flux` and `Mono`
2023-02-21 12:02:15 -05:00
Artem Bilan
b482b002cb GH-4014: MQTT ClientManager: completion timeouts (#8552)
Fixes https://github.com/spring-projects/spring-integration/issues/4014

The `ClientManager` implementations uses by mistake a `connectionTimeout` for operations with completion wait

* Introduce `completionTimeout` and `disconnectCompletionTimeout` for `ClientManager`
abstraction to realign the logic with existing channel adapters and Paho Client by itself.
* Deprecate `DEFAULT_COMPLETION_TIMEOUT` and `DISCONNECT_COMPLETION_TIMEOUT` constants
in the `AbstractMqttMessageDrivenChannelAdapter` in favor of respective replacement in the `ClientManager`
* Pull `disconnectCompletionTimeout` property from the `MqttPahoMessageDrivenChannelAdapter` to its superclass
* Use new `disconnectCompletionTimeout` in the `Mqttv5PahoMessageDrivenChannelAdapter` for similar `disconnectForcibly()` call
* Fix Lifecycle race condition when `ClientManager` is started by the outbound channel adapter
(`Integer.MIN_VALUE` phase and auto-startup - see `DefaultLifecycleProcessor.doStart()` and logic around `dependencies`)
which is much earlier than `MessageProducerSupport` (`Integer.MAX_VALUE / 2` phase) and there a `connectComplete()` callback
might be called before the `MessageProducerSupport.start()`.
For that purpose check for an `isRunning()` in the `connectComplete()` before subscribing and set `readyToSubscribeOnStart` flag
to `subscribe()` in a `doStart()` of this `MqttMessageDrivenChannelAdapter`
* Remove redundant `MqttPahoMessageDrivenChannelAdapter.cleanSession` property in favor of
`this.clientFactory.getConnectionOptions().isCleanSession()` call

GH-8550: MQTT: Always re-subscribe on re-connect

Fixes https://github.com/spring-projects/spring-integration/issues/8550

Turns out the Paho MQTT client does not re-subscribe when connection
re-established on automatic reconnection

* Fix `AbstractMqttMessageDrivenChannelAdapter` to always subscribe to their topics
in the `connectComplete()` independently of the `reconnect` status
* Verify behavior with `MOSQUITTO_CONTAINER` image restart in Docker
2023-02-15 17:26:12 -05:00
abilan
3d245276e4 Fix new Sonar smells 2023-02-14 17:02:23 -05:00
abilan
4cd1085f94 Upgrade some dependencies
* Remove already redundant `parentObservation` population in the `AbstractMessageChannel`:
now it is handled properly by the `SimpleObservation` ctor
2023-02-14 15:01:42 -05:00
Gary Russell
e8a9f95ca1 GH-4013: TCP DSL Improvements
Resolves https://github.com/spring-projects/spring-integration/issues/4013

Add Net/NIO specific Server/Client connection factory specs.

* Shorten DSL method names, as suggested.
2023-02-08 17:01:44 -05:00
Ivan Zaitsev
e6d0a4f826 GH-4008: ZK: Add leader and participants support
Fixes https://github.com/spring-projects/spring-integration/issues/4008

Impossible to retrieve current leader id from ZK `LeaderInitiator`

* change return type of `LeaderInitiator.getContext()` from `Context` to `CuratorContext`
* add `getLeader()` method to `CuratorContext`
* add `getParticipants()` method to `CuratorContext`
2023-02-07 10:36:29 -05:00
Artem Bilan
6a2ff0cd99 GH-4001: Doc for cooperation with some HZ objects (#4003)
* GH-4001: Doc for cooperation with some HZ objects

Fixes https://github.com/spring-projects/spring-integration/issues/4001

The `IQueue`, `ITopic` and `IExecutorService` can be used with Spring Integration
channel as is without any extra component implementations.

* Document the cooperation feature with Hazelcast objects via samples

* * Add a sample about an Inbound Channel Adapter on the `IQueue`

* Fix language in docs

Co-authored-by: Gary Russell <grussell@vmware.com>

---------

Co-authored-by: Gary Russell <grussell@vmware.com>
2023-02-06 12:20:42 -05:00
Artem Bilan
44000b9606 GH-4002: Deprecate ConsumerStopAction in MQTT (#4006)
Fixes https://github.com/spring-projects/spring-integration/issues/4002

Turns out the `ConsumerStopAction` was introduced in a point version to mitigate an unsubscription bug
and let to preserve a previous behaviour.

* Deprecate `ConsumerStopAction` in favor of just `cleanSession` flag in the `MqttConnectOptions`

**Cherry-pick to `5.5.x`**
2023-02-06 11:58:41 -05:00
Artem Bilan
d9d7c49aac Propagate and Observation from Reactive context (#3999)
To propagate an `Observation` from reactive stream (e.g. WebFlux)
we have to capture its context and set it into the current thread scope.

* Add a `io.micrometer:context-propagation` dependency to support reactive context propagation
* Populate a `parentObservation` in the `IntegrationObservation.PRODUCER.observation()`
since it is not available for tracing on `Observation.onStart()`.
Might be tentative until upcoming fix in Micrometer Observation
* Populate from reactive context in the `WebFluxInboundEndpoint` where we use just `send()` operation downstream
* Populate from reactive context in the `MessagingGatewaySupport` where we use `send()` operation downstream or `FluxMessageChannel.subscribeTo()`
* Use `contextCapture()` in the `FluxMessageChannel` to gather a `ThreadLocal` info into a Reactor context
and then set back to `ThreadLocal` in the `transformDeferredContextual()` which really happens on a different thread
* Verify a trace propagation from WebFlux to an integration flow via Brave instrumentation in the `WebFluxObservationPropagationTests`
2023-02-01 14:13:40 -05:00
Artem Bilan
841289002c GH-3998: Fix gateway docs for @Payload (#4000)
* GH-3998: Fix gateway docs for `@Payload`

Fixes https://github.com/spring-projects/spring-integration/issues/3998

The `GatewayProxyFactoryBean` now deals only with a `MethodArgsHolder` as a root evaluation context object.
There is no `#args` and `#method` SpEL variables anymore.
However, the `gateway.adoc` still refer to those.

* Fix `gateway.adoc` for a proper expressions and actual wording

* * Cross link to `gateway-expressions` paragraph for better context
2023-02-01 14:05:20 -05:00
Artem Bilan
f01e2b8553 GH-3994: Register native hints for Graph model (#3996)
Fixes https://github.com/spring-projects/spring-integration/issues/3994

Essentially, migrate those hints from Spring Boot Actuator:
an `IntegrationGraphServer` can be used without Spring Boot

* Introduce `IntegrationGraphRuntimeHints` - implementation of `RuntimeHintsRegistrar`
to register reflection hints for `Graph` and top-level `IntegrationNode` types.
* Use `@ImportRuntimeHints` on the `IntegrationGraphServer` to make those hints
conditional.
2023-01-23 14:22:42 -05:00
Artem Bilan
ebba37497f GH-3993: Fix async race condition in TcpOutGateway (#3995)
* GH-3993: Fix async race condition in TcpOutGateway

Fixes https://github.com/spring-projects/spring-integration/issues/3993

When `TcpOutboundGateway` is in an `async` mode and `CCF` is configured
not for `singleUse` an `Semaphore` around an obtained `TcpConnection` is involved.
If we fail on `TcpConnection.send()`, resources are not clean up, including the
mentioned `Semaphore`: in async mode this happens only when we receive a reply.

* Catch an exception on the `TcpConnection.send()` and perform `cleanUp()` in async mode.
* Add `cleanUp()` into a scheduled task from the `TcpOutboundGateway.AsyncReply`
when no reply arrives in time.
* Optimize `TcpOutboundGateway.AsyncReply` behavior to cancel no-reply scheduled task
when reply arrives into a `CompletableFuture`

**Cherry-pick to `5.5.x`**

* * Call `cleanUp()` from no response scheduled task
only if `future.completeExceptionally()` is `true`
2023-01-23 11:07:19 -05:00
Spring Builds
f8c0779964 [artifactory-release] Next development version 2023-01-18 18:20:29 +00:00
Spring Builds
480a9735bf [artifactory-release] Release version 6.0.2 2023-01-18 18:20:26 +00:00
abilan
330f1cdb7e Increase group timeout for AggregatorIntTests
https://build.spring.io/browse/INT-MAIN-561/
2023-01-18 12:24:09 -05:00
abilan
298b2403d9 Exclude org.glassfish.jaxb from spring-ws-core
The `spring-integration-ws` modules relies on the `com.sun.xml.bind:jaxb-impl`
as `provided` dependency
2023-01-18 11:51:40 -05:00
abilan
4be99de1f4 Upgrade dependencies; prepare for release
* Fix mail tests for the latest Greenmail changes
2023-01-18 11:03:10 -05:00
abilan
05659301df Fix race condition in TcpOutGateTests.testAsync
The `ChannelInterceptor.postSend()` may be called when
`MessageChannel.receive()` has already done its job polling from
the queue where message appears in the `MessageChannel.doSend()`

* Use `ChannelInterceptor.preSend()` contract instead to obtaine info about the current thread
2023-01-18 09:14:13 -05:00
abilan
a1f57e40cd Fix reactive error handling for request-reply
Related to https://stackoverflow.com/questions/75109345/spring-integration-webflux-inboundgateway-replychannel-for-error-response

The `MessagingGatewaySupport.doSendAndReceiveMessageReactive()` uses `MutableMessageBuilder`
to build a new message for next `send` operation.
Even if this is an error flow, the provided `ErrorMessage` becomes a plain `MutableMessage`.
This may break some downstream logics, like `TracingChannelInterceptor` from Spring Cloud Sleuth,
which checks for the `Message` class to rebuild or reuse a message content.
Therefore, an error handling flow is not able to extract error info because it is just lost.

* Fix `MessagingGatewaySupport.doSendAndReceiveMessageReactive()` to check for message type before
choosing an `AbstractIntegrationMessageBuilder` impl for building a new message.
The regular `MessageBuilder` just builds a new `ErrorMessage` for an exception payload.
* Add `filter()` into a `WebFluxDslTests` error handling flow to be sure that message for
error sub-flow is really an `ErrorMessage`
2023-01-17 14:50:27 -05:00
abilan
2c722851fe GH-3990: Fix JsonPath native hint registration
Fixes https://github.com/spring-projects/spring-integration/issues/3990

Turns out just being on the classpath doesn’t make the type reachable.
If it’s only accessed reflectively then it’s not reachable.
This is exaclt what happened with our `JsonPathUtils` which is used via
reflection from SpEL when that calls its method via function reference

* Change `onReachableType()` logic for `com.jayway.jsonpath.JsonPath` type
to `ClassUtils.isPresent()` on `JsonPathUtils` reflection hint registration.
2023-01-14 13:36:01 -05:00
abilan
9dd9f08181 Use switch expression; some other clean up 2023-01-13 16:00:19 -05:00
abilan
fc3b95ea79 Debug not resolved channel in Router
Currently, when `!resolutionRequired` not resolved channel name
is ignored silently, and we go ahead to `defaultOutputChannel` or
exception thrown

* For better end-user experience `DEBUG` not resolved and ignored channel name if `!resolutionRequired`
2023-01-13 15:12:44 -05:00
Artem Bilan
d298df8d0f Revise JS support for regular JVM (#3989)
* Revise JS support for regular JVM

Turns out that we just need to have `org.graalvm.sdk:graal-sdk` and `org.graalvm.js:js`
dependencies for regular JVM to enable JavaScript support for Spring Integration Scripting module

* Add respective `providedImplementation` dependencies
* Remove `@EnabledIfSystemProperty` from unit tests
* Mention those dependencies in the doc

* Rework sentence in the doc for better English

Co-authored-by: Gary Russell <grussell@vmware.com>

Co-authored-by: Gary Russell <grussell@vmware.com>
2023-01-11 13:34:28 -05:00
abilan
74320381ba Some tweaks for SimpleMessageGroupTests
**Cherry-pick to `5.5.x`**
2023-01-09 16:27:06 -05:00
abilan
4283a5532a GH-3986: Integration mock: fix ReactiveMH support
Fixes https://github.com/spring-projects/spring-integration/issues/3986

The `ReactiveStreamsConsumer` in addition to plain `Subscriber` and `MessageHandler`
also supports a `ReactiveMessageHandler`, but `MockIntegrationContext` doesn't
handle a scenario when `ReactiveMessageHandler` is provided for consumer

* Rework the logic in the `MockIntegrationContext` to substitute a `ReactiveMessageHandler`
in the `ReactiveStreamsConsumer` which has a precedence in its logic over plain `Subscriber`.
* Wrap a plain `MessageHandler` mock into a `ReactiveMessageHandler` before substitution
in the `ReactiveStreamsConsumer`
* Reset `ReactiveStreamsConsumer.reactiveMessageHandler` with source `ReactiveMessageHandler`
or `null` respectively to an original `ReactiveStreamsConsumer` configuration
* Mention `ReactiveMessageHandler` use-case in the `testing.adoc`

**Cherry-pick to `5.5.x`**
2023-01-09 15:37:06 -05:00
Artem Bilan
308f3fadeb Do not build exception instances in advance (#3983)
* Do not build exception instances in advance

When no `cause` and no clean context of the exception thrown,
the code place where an exception has been created is confusing.

* Fix `SimpleMessageStore` to create an `out of capacity` exception in the
`addMessagesToGroup()` exactly at the point where it is thrown
* Fix `FunctionExpression` and `SupplierExpression` do not pre-create `readOnlyException`:
it is unlikely these kind of expressions are going to be used in the SpEL `write` context,
so we save some time and memory not creating extra object and the plain call `throw new`
gives us a clean context what method call has ended up with such an exception

* * Extract `outOfCapacityException` to the method in the `SimpleMessageStore`
to avoid duplication.
Even if we got in the end extra line in th stack trace, it is still clear from
where it is thrown:

```
org.springframework.messaging.MessagingException: SimpleMessageStore was out of capacity (1) for group 'foo', try constructing it with a larger number.

	at org.springframework.integration.store.SimpleMessageStore.outOfCapacityException(SimpleMessageStore.java:324)
	at org.springframework.integration.store.SimpleMessageStore.addMessagesToGroup(SimpleMessageStore.java:302)
	at org.springframework.integration.store.AbstractMessageGroupStore.addMessageToGroup(AbstractMessageGroupStore.java:189)
	at org.springframework.integration.store.SimpleMessageStoreTests.shouldNotHoldMoreThanGroupCapacity(SimpleMessageStoreTests.java:128)
```
2023-01-05 11:35:24 -05:00
abilan
cf5f218449 Fix new Sonar smells 2023-01-05 10:19:26 -05:00
kdebski85
854e555e4e GH-3980: Fix DefaultSftpSFactory for concurrency
Fixes https://github.com/spring-projects/spring-integration/issues/3980

When not `isSharedSession`, the `initClient()` is called for every session
we request from the factory and in concurrent calls we end up with not initialized SSH client
in some threads.

* Add `synchronized` double check logic to the `initClient()` to block other threads while the first one
initialize the client
* Use `volatile boolean` instead of `AtomicBoolean` and change its state when `SshClient` is created and started
2023-01-05 10:01:48 -05:00
abilan
f8fff81886 Fix new Sonar smells 2022-12-21 13:39:18 -05:00
abilan
679ce6ff36 Upgrade to Gradle 7.6
* Fix `pr-build-workflow.yml` removing unused services: now they are pulled by Testcontainers
* Use official `rabbitmq:management` image instead of `MQTT`-based.
The `MQTT` is now tested with Testcontainers and Mosquitto broker image
2022-12-21 13:04:17 -05:00
abilan
19d6b7617f More Mockito fixes for test XML configs
Looks like sometime Spring Framework XML parser can properly determine the target factory method to chose,
but sometimes it does that in a wrong order.

* Add `type="java.lang.Class"` to the ctor args everywhere for `class="org.mockito.Mockito" factory-method="mock"`
`<bean>` definitions
2022-12-21 11:16:56 -05:00
Spring Builds
e74393f995 [artifactory-release] Next development version 2022-12-21 15:42:34 +00:00
Spring Builds
e990486025 [artifactory-release] Release version 6.0.1 2022-12-21 15:42:31 +00:00
abilan
033cb7695b Migrate Mockito-effected test classes to JUnit 5 2022-12-21 09:42:18 -05:00
abilan
eb570ec447 More test XML configs for latest Mockito 2022-12-20 21:14:02 -05:00
abilan
376d5dfc16 Fix Rsocket test XML configs for latest Mockito 2022-12-20 17:57:46 -05:00
abilan
30c0ea2791 Fix JPA test XML configs for latest Mockito 2022-12-20 17:52:41 -05:00
abilan
097d3e54b7 Fix mail test XML config for latest Mockito 2022-12-20 17:36:52 -05:00
abilan
5c926e84ba Add missed type="java.lang.Class" to IdRecTests 2022-12-20 17:19:25 -05:00
abilan
aa761b44b4 Fix more test XML configs for latest Mockito 2022-12-20 17:08:34 -05:00