488 Commits

Author SHA1 Message Date
Eddie Cho
0386291c06 GH-3444: Add Custom TTL support for RedisLock, and JdbcLock
Fixes: #3444

* Add `DistributedLock` interface which is implemented by `RedisLock` and `JdbcLock`.
* Modify `LockRegistry`, `ExpirableLockRegistry`, `RenewableLockRegistry` interfaces.
* Modify implementation of `DefaultLockRepository, `JdbcLockRegistry`, `RedisLockRegistry`
* Modify ddl of `INT_LOCK` table.
* Maintain test cases and documents.

Signed-off-by: Eddie Cho <chochoforwork@gmail.com>

GH-3444: Add Custom TTL support for RedisLock, and JdbcLock

Fixes: #3444

* Modify `LockRegistry`, `DistributedLock` interfaces.
* Modify implementation of `DefaultLockRepository, `JdbcLockRegistry`, `RedisLockRegistry`
* Modify ddl of `INT_LOCK` table.
* Maintain test cases and documents.

Signed-off-by: Eddie Cho <chochoforwork@gmail.com>

GH-3444: Add Custom TTL support for RedisLock, and JdbcLock

Fixes: #3444

* Modify DistributedLock` interfaces.
* Modify implementation of `JdbcLockRegistry`, `RedisLockRegistry`.
* Modify JavaDoc.

Signed-off-by: Eddie Cho <chochoforwork@gmail.com>

GH-3444: Add Custom TTL support for RedisLock, and JdbcLock

Fixes: #3444

* Maintain document

Signed-off-by: Eddie Cho <chochoforwork@gmail.com>

GH-3444: Add Custom TTL support for RedisLock, and JdbcLock

Fixes: #3444

* Add @Deprecated

Signed-off-by: Eddie Cho <chochoforwork@gmail.com>
2025-06-16 07:18:23 -04:00
Artem Bilan
7221d23447 Remove extra blank line in the end of MySqlTxTimeoutMessageStoreTests
Signed-off-by: Artem Bilan <artem.bilan@broadcom.com>
2025-06-06 19:41:04 -04:00
Artem Bilan
2ff14c70c8 Disable sporadic MySqlTxTimeoutMessageStoreTests.testInt2993IdCacheConcurrency 2025-06-06 17:58:49 -04:00
Artem Bilan
b8116d59a9 Clean up and improve Java DSL for JDBC
Follow up for: https://github.com/spring-projects/spring-integration/pull/10081

* Rename `StoredProcExecutorConfigurer` to `StoredProcExecutorSpec`
* Add `Jdbc.storedProcExecutorSpec()` factory
* Improve logic of `StoredProcExecutor`-based Java DSL classes to handle an external `StoredProcExecutor` as well
* Add `package-info.java` into the `jdbc/dsl` package
* Add `/jdbc/dsl.adoc` and respective `What's New` entry
2025-06-06 14:11:34 -04:00
Jiandong
cd15675734 GH-8467: Add Java DSL support for JDBC module
Fixes: https://github.com/spring-projects/spring-integration/issues/8467

Signed-off-by: Jiandong Ma <jiandong.ma.cn@gmail.com>
2025-06-06 12:30:41 -04:00
Artem Bilan
d9259f5167 Upgrade to Java 24; Kotlin 2.1
* Rearrange `JavaCompile` and `KotlinCompilationTask` Gradle options
* Comment out `Werror` for `Javadoc` tasks to avoid build failure
* Disable `UdpChannelAdapterTests.testMulticastReceiver()` since it fails somehow on Java `23` & `24`
* Disable `MySqlTxTimeoutMessageStoreTests.testInt3181ConcurrentPolling()` since it is not stable
2025-06-02 15:05:17 -04:00
Jiandong
01db420bae GH-10045: Enable JDBC test cases with TestContainers approach
Fixes: https://github.com/spring-projects/spring-integration/issues/10045

Signed-off-by: Jiandong Ma <jiandong.ma.cn@gmail.com>
2025-05-30 12:01:48 -04:00
Jiandong
5bdf35a7d9 Migrate few modules to Junit Jupiter
including: `spring-integration-amqp`, `spring-integration-file`, 'spring-integration-groovy'

Signed-off-by: Jiandong Ma <jiandong.ma.cn@gmail.com>
2025-05-20 10:40:20 -04:00
Artem Bilan
3ad8828657 GH-6380: Support Map as input in BeanPropertySqlParameterSourceFactory
Fixes: https://github.com/spring-projects/spring-integration/issues/6380

The `MapSqlParameterSource` is much faster, then reflection or SpEL,
so, it would be great to have such an interaction when we evaluate values for SQL queries

* Enhance `BeanPropertySqlParameterSourceFactory` to use `MapSqlParameterSource` if `input` is a `Map`
* Expose `JdbcMessageHandler.usePayloadAsParameterSource` for convenience with `SqlParameterSourceFactory`,
especially when the payload is a map
2025-02-27 13:24:49 -05:00
Artem Bilan
32e3d18c94 Fix race condition in the PostgresChannelMessageTableSubscriberTests
Adding two messages into a group may end up with wrong insert order.
Or better to say the timestamp of first messages inserted might be behind in the future after the second one.
This leads to a wrong order return for polling operation and, therefore, verification in the test.

* Fix `PostgresChannelMessageTableSubscriberTests` inserting `Thread.sleep(100);`
between `messageStore.addMessageToGroup()` operations
2025-02-11 11:59:54 -05:00
Artem Bilan
370f308fe7 GH-9818: Fix typos in JavaDocs of JDBC components
Fixes: #9818
Issue link: https://github.com/spring-projects/spring-integration/issues/9818

**Auto-cherry-pick to `6.4.x` & `6.3.x`**
2025-02-11 11:13:55 -05:00
Artem Bilan
177bda58c5 GH-9744: Remove deprecated LobHandler references
Fixes: https://github.com/spring-projects/spring-integration/issues/9744
2025-01-08 12:28:56 -05:00
NaccOll
9962ee49a2 GH-5123: Add LockRegistry to AbstractMessageGroupStore
Fixes: https://github.com/spring-projects/spring-integration/issues/5123

When `RedisMessageStore`, for example, adds and removes messages, it operates on two keys separately, which may cause problems in multi-threading due to non-atomic operations.
Although using Redis to delay messages is not a good idea, the abnormal loss of messages in the logs alerted me when the number of requests was not large.
By comparing the logs, the problem that the message group representing the metadata is not consistent with the actual message.

A simple solution is to add lock like in the `SimpleMessageStore`, which is also the approach taken in this pull request.

* Add `LockRegistry` to `AbstractMessageGroupStore`
* Normalize access levels and method name about the lock of `MessageGroupStore`
* Add document about the lock of `AbstractMessageGroupStore`
2025-01-08 12:18:12 -05:00
Artem Bilan
0d2595ef7c GH-9620: Use Locale.ROOT for neutral, case insensitive comparisons
Fixes: #9620
Issue link: https://github.com/spring-projects/spring-integration/issues/9620

**Auto-cherry-pick to `6.3.x` & `6.2.x`**
2024-10-31 10:59:05 -04:00
Eddie Cho
bab7e8d579 DefaultLockRepository: Use == 1 for delete and renew query results
Some claim that it might improve code readability.
2024-10-30 16:01:04 -04:00
Artem Bilan
15e914b75b Remove Bamboo mentioning from the tests 2024-10-18 14:33:43 -04:00
Tran Ngoc Nhan
fc377126de Modernize code for diamond, isEmpty & pattern matching 2024-09-23 14:42:38 -04:00
Artem Bilan
98d0266ba0 GH-9481: Fix JdbcMetadataStore for PostgreSQL & MySQL
Fixes: #9481
Issue link: https://github.com/spring-projects/spring-integration/issues/9481

MySQL throws `CannotAcquireLockException` in case of duplicate key failure.
PostgreSQL just rollbacks a transaction not letting us move on with a `SELECT`

* Include `TransientDataAccessException` to the catch block of the `INSERT`
to ignore it for the subsequent `SELECT`
* Add logic to determine `PostgreSQL` database vendor and include `ON CONFLICT DO NOTHING`
hint into the `INSERT` to not fail in case of duplicate key found on `putIfAbsent` operation

**Auto-cherry-pick to `6.3.x` & `6.2.x`**
2024-09-17 15:22:08 -04:00
Artem Bilan
4d787554b8 GH-9381: Introduce Control Bus commands management
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
2024-08-13 13:26:27 -04:00
Sanghyuk Jung
32f2668260 Remove duplicated "the" in Javadocs 2024-08-02 19:26:09 -04:00
Eddie Cho
53445fe771 GH-9291: Enhanced unlock() method of JdbcLock to verify successful unlocking
Fixes: #9291

* Modify `unlock()` method of `JdbcLock`: if the lock ownership can not be removed due to data expiration, a `ConcurrentModificationException` should be thrown.
* Modify `unlock()` method of `RedisLock`: if the lock ownership can not be removed due to data expiration, a `ConcurrentModificationException` should be thrown.
* Maintain test cases
* Document the new behavior
2024-07-02 15:48:07 -04:00
Artem Bilan
26fc907558 Fix JdbcLockRegistryTests.testTwoThreadsDifferentRegistries()
The test is supposed to verify against different clients, but same DB
2024-07-02 10:55:13 -04:00
Artem Bilan
27b194f537 Remove unused import from JdbcChannelMessageStore 2024-06-04 17:36:11 -04:00
Artem Bilan
d76174edb1 GH-9192: Deprecate LobHandler usage
Fixes: #9192

With modern drivers we don't need BLOB-specific handling anymore.
The regular `PreparedStatement.setBytes()` and `ResultSet.getBytes()`
are enough for our serialized messages
2024-06-04 17:28:17 -04:00
Johannes Edmeier
da29e2da6a PostgresChannelMessageTableSubscriber: Renew connection only if invalid
Fixes: #9111

An evolution of the #9061: renew the connection only when we need to.

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-05-21 10:20:29 -04:00
Johannes Edmeier
642278dad1 GH-9061: renew connection in PostgresChannelMessageTableSubscriber
Fixes: #9061

`PostgresChannelMessageTableSubscriber` never renews the connection.
This causes problems on DB failover. 
With this change the connection is renewed when notifications are not received for a certain time.


**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-04-01 13:05:56 -04:00
Artem Bilan
c155d5d418 Add EmptyLineSeparator Checkstyle rule
* Support "blank lines around" via `spring-framework.xml` IDEA config
* Fix all the Checkstyle violations
2024-03-27 16:54:25 -04:00
Artem Bilan
f71a2234d8 GH-9050: JDBC LockRepository: Use Timestamp instead of LocalDateTime
Fixes: #9050

Turns out not all JDBC drivers support a `LocalDateTime` type conversion.

* Use `Timestamp.valueOf(LocalDateTime)` for `TIMESTAMP` params of the queries
in the `DefaultLockRepository`

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-03-25 13:12:37 -04:00
Artem Bilan
676733ccf7 GH-8998: Catch DataIntegrityViolationException instead
Fixes: #8998

Apparently some databases don't throw a proper code to identify a `DuplicateKeyException`, so better to catch `DataIntegrityViolationException` with the same meaning.

**Auto-cherry-pick to `6.2.x` & `6.1.x`**
2024-03-12 15:53:37 -04:00
Artem Bilan
6f3b642f73 Upgrade dependencies to the latest minor versions
* Fix deprecation from AssertJ
2024-02-28 10:59:03 -05:00
Artem Bilan
ae5472e2f5 GH-8863: Remove deprecated API from previous versions
Fixes: #8863
2024-01-17 12:31:43 -05:00
Artem Bilan
5370d50932 GH-8773: Fix MGS for removal from group
Fixes https://github.com/spring-projects/spring-integration/issues/8773

The https://github.com/spring-projects/spring-integration/issues/8732 introduced a filtering for messages in group.
So, plain `removeMessage()` doesn't work any more if message is connected to some group yet.
Therefore, `DelayHandler` is failing.

* Introduce `getMessageFromGroup()` and `removeMessageFromGroupById()` into `MessageGroupStore` API
and implement it respectively in all the stores
* Remove `@LongRunningTest` from delayer integration tests and adjust its config to delay not for a long

**Cherry-pick to `6.1.x`**
2023-11-03 19:37:38 +01:00
Artem Bilan
769367deea GH-8770: Add PostgresSubsChannel.errorHandler (#8777)
* GH-8770: Add `PostgresSubsChannel.errorHandler`

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

The problem with the `PostgresSubscribableChannel.notifyUpdate()` is that the try-catch block is outside the loop,
so the loop will die on an exception, leaving further messages unprocessed.

* Add ``PostgresSubscribableChannel.errorHandler` option to be invoked
after a `RetryTemplate` and for every failed message.
* The `askForMessage()` new logic is to catch an exception on a message and call `errorHandler`
returning a `FALLBACK_STUB` to continue an outer loop in the `notifyUpdate()`

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

* * Rename private `PostgresSubscribableChannel.askForMessage()` method to more specific `pollAndDispatchMessage()`
2023-10-25 13:26:24 -04:00
Igor Dianov
6db704158f GH-8768: Fix countQuery in JdbcMetadataStore
Fixes https://github.com/spring-projects/spring-integration/issues/8768

The `countQuery` is accidentally formatted against `putIfAbsentValueQuery`
2023-10-18 09:57:49 -04:00
Artem Bilan
e933d63868 Fix PostgresSubscribableChannel race condition
The `PostgresSubscribableChannel` uses a task executor
for dispatching messages.
Even if we stop `PostgresChannelMessageTableSubscriber` and
unsubscribe from the channel, the task might be ongoing.

* Use explicit `ThreadPoolTaskExecutor` in the test
to shout it down and wait for tasks to be completed before
verifying DB status
* Optimize `PostgresSubscribableChannel` to mark TX for rollback
when we got a message from DB, but no handlers subscribed
2023-10-17 13:25:05 -04:00
Johannes Edmeier
87a2ac5b5c GH-8760 Postgres: using DELETE ... RETURNING
Fixes https://github.com/spring-projects/spring-integration/issues/8760

* Make `PostgresChannelMessageStoreQueryProvider` to use single `DELETE ... RETURNING` for polling statements
* Add `isUsingSingleStatementForPoll` and use it from `JdbcChannelMessageStore`
* Execute Postgres init scripts to `PostgresContainerTest`
* Code clean up
* Document the new feature
2023-10-17 11:26:46 -04:00
Artem Bilan
fa06940f6d GH-8748: JDBC locks: use READ_COMMITTED isolation (#8749)
Fixes https://github.com/spring-projects/spring-integration/issues/8748

The Oracle DB throws `ORA-08177: can't serialize access for this transaction`
when other transaction on the row has begun

* Change the isolation for `DefaultLockRepository.acquire()` transaction
to the `READ_COMMITTED` for what database automatically and silently
restarts the entire SQL statement, and no error occurs.
* Add `oracle` dependencies to JDBC module
* Introduce `OracleContainerTest` and implement it for `OracleLockRegistryTests`

**Cherry-pick to `6.1.x` & `6.0.x`**
2023-10-09 11:52:40 -04:00
Artem Bilan
7b4d4561f5 Update dependencies; prepare for release
* Fix Checkstyle violations for `private` inner classes where they have to be also `final`
* Fix deprecations after upgrades
* Remove manual coroutines handling in the `GatewayProxyFactoryBean`
in favor of the same functionality in the `JdkDynamicProxy`
2023-09-19 20:49:14 -04:00
Myeonghyeon-Lee
0f1304494f Fix Checkstyle violation in the JdbcLockRegistry
**Cherry-pick to `6.1.x` & `6.0.x`**
2023-09-18 10:59:28 -04:00
Myeonghyeon-Lee
50c53e08aa GH-8730: Fix isAcquiredInThisProcess to use localLock
The `ExpirableLockRegistry.expireUnusedOlderThan()` uses a query to the target store by mistake.
The logic of this API is indeed about the local cache for those lock instances.
We cannot effect any other processes with this cache. 
And even if we remove our local instance while it is locked in other process, 
that doesn't mean that on the next `obtain()` call, when we got a fresh local instance, we will be able to acquire a lock in target store.

* Fix `isAcquiredInThisProcess()` to check only `localLock.isLocked()`

**Cherry-pick to `6.1.x` & `6.0.x`**
2023-09-18 10:39:37 -04:00
Artem Bilan
78367f2b73 Fix PostgresSubscribableChannel.notifyUpdate()
When transaction is configured for the `PostgresSubscribableChannel.notifyUpdate()`
and it is rolled back, the next poll in that loop will return the same message.
Again and again if transaction is always rolled back.
This leads to the condition when we never leave this loop even if
we fully unsubscribed from this channel.

The issue has need spotted after introducing `SKIP LOCKED`
for `PostgresChannelMessageStoreQueryProvider` which leads to
the locked record in DB in the mentioned above transaction.

* Introduce `PostgresSubscribableChannel.hasHandlers` flag
to check in the `notifyUpdate()` before performing poll query in DB.

**Cherry-pick to `6.1.x` & `6.0.x`**
2023-09-18 14:18:40 +02:00
Artem Bilan
df67c59f8e GH-8732 Don't remove JDBC message if other groups (#8733)
* GH-8732 Don't remove JDBC message if other groups

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

When same message is added into different groups,
its record in the `INT_MESSAGE` must remain until the last group is removed

* Improve `JdbcMessageStore.DELETE_MESSAGES_FROM_GROUP` SQL
to ignore those messages for removal which has other group records in the `INT_GROUP_TO_MESSAGE` table

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

* * Fix `JdbcMessageStore.removeMessage()` and `removeMessagesFromGroup()`
to remove from `INT_MESSAGE` only if there is no other records in `INT_GROUP_TO_MESSAGE`

* * Improve `MessageStore.removeMessage()` Javadoc
mentioning `MessageGroupStore` specifics
2023-09-14 12:58:07 -04:00
Artem Bilan
eef070a3d9 Some code clean up for ChMessStoreQueryProvider
* Add a version for deprecation on `AbstractChannelMessageStoreQueryProvider`
* Remove dead links from `ChannelMessageStoreQueryProvider` impl JavaDocs
* Use text blocks for long query strings
* Move `SELECT_COMMON` constant to the `ChannelMessageStoreQueryProvider` interface
2023-09-01 11:15:09 -04:00
Adama Sorho
0a95091331 Deprecate AbstractChannelMessageStoreQueryProvider
* Move methods from `AbstractChannelMessageStoreQueryProvider` to `default` in the `ChannelMessageStoreQueryProvider` interface.
* Remove usage of this deprecated method.
* Fix `message-store.adoc` to mention `ChannelMessageStoreQueryProvider` instead of deprecated abstract class.
2023-09-01 10:32:20 -04:00
Adama Sorho
571ed20905 GH-8711: Add SKIP LOCKED for QueryProviders
Fixes https://github.com/spring-projects/spring-integration/issues/8711

* Add `SKIP LOCKED` into `MySqlChannelMessageStoreQueryProvider` and `PostgresChannelMessageStoreQueryProvider`
* Stop the `postgresChannelMessageTableSubscriber` after the latch waiting 10s has been passed in `testMessagesDispatchedInTransaction` test case
2023-08-31 12:51:39 -04:00
Artem Bilan
7dcc0bb125 GH-8680: Check DB for table on start (#8690)
* GH-8680: Check DB for table on start

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

If database is not initialized properly before application start, we may lose messages
at runtime when we fail to insert data into DB

* Implement `SmartLifecycle` on `JdbcMessageStore`, `JdbcChannelMessageStore`,
`JdbcMetadataStore`, and `DefaultLockRepository` to perform `SELECT COUNT` query in `start()`
to fail fast if no required table is present.
* Refactor `AbstractJdbcChannelMessageStoreTests` into JUnit 5 and use `MySqlContainerTest`
for more coverage
* Fix newly failed tests which had DB not initialized before
* Exclude `commons-logging` from `commons-dbcp2` dependency to avoid
classpath conflict
* Document the new feature

* * Fix HTTP URL in the `DataSource-mysql-context.xml`

* Fix language in docs

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

* * Add `setCheckDatabaseOnStart(false)` to disable the check query for all the SI JDBC components

* Fix language in Javadocs

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

---------

Co-authored-by: Gary Russell <grussell@vmware.com>
2023-07-28 14:47:49 -04:00
Christian Tzolov
c38ed96ee9 GH-8643: Replace synchronized with Lock
Fixes https://github.com/spring-projects/spring-integration/issues/8643

* First pass - trivial synchronized blocks
  - Convert the "trivial" `synchronized` block into `ReentrantLock`.

* fix checkstyle

* use blocking lock

* Secon pass - handle multi-lock cases

* javadoc + year

* addres first batch of review suggestions

* fix checkstyle issues

* fix the mqtt parent/child lock monitor sharing

* fix the mqtt parent/child lock monitor sharing, v2

* patch the stomp test
2023-06-21 13:25:45 -04:00
Artem Bilan
4db9bad50d GH-8642: Revise executors in the project (#8647)
* GH-8642: Revise executors in the project

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

* Rework some `Executors.newSingleThreadExecutor()` to `ExecutorServiceAdapter(new SimpleAsyncTaskExecutor())`
* Expose `TaskExecutor` setters; deprecate `ExecutorService`-based
* Some other code clean up in the effected classes: `LogAccessor`, no `synchronized` in critical blocks
* Give a meaningful prefix for default threads in the context of components, e.g. `SubscribableRedisChannel` - `getBeanName() + "-"`

* * Fix `PostgresChannelMessageTableSubscriberTests` for
`PostgresSubscribableChannel` initialization to let it create
its internal `Executor`

* Use an `AsyncTaskExecutor` injection instead of `ExecutorServiceAdapter` wrapping

* Fix `LockRegistryLeaderInitiatorTests` for `taskExecutor` injection

* Bring back `LockRegistryLeaderInitiator.setExecutorService()`
as an accident after property auto-renaming
2023-06-14 13:33:46 -04:00
abilan
7655d97cee Fix code typos in filter.adoc & router.adoc
* Fix race condition in the `JdbcPollingChannelAdapterParserTests`
making SELECT and UPDATE as a part of the same transaction
* Remove `inProcess = JAVA_EXEC` from ASCIIDoc Gradle tasks in attempt
to make them working in parallel
2023-06-07 15:19:03 -04:00
Artem Bilan
ba417de680 Remove deprecations from previous versions (#8628) 2023-05-22 11:19:13 -04:00