Commit Graph

475 Commits

Author SHA1 Message Date
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
abilan
3618965491 GH-8623: DefLockRepository: back to LocalDateTime
Fixes https://github.com/spring-projects/spring-integration/issues/8623

Turns out not all JDBC drivers (or RDBMS vendors) support `java.time.Instant`
mapping to their `TIMESTAMP` type.
For example the PostgreSQL fails like:
```
org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.time.Instant.
```

* Use `LocalDateTime.now(ZoneOffset.UTC)` instead `Instant.now()`.
Essentially bringing back the behavior from the previous version
2023-05-16 11:00:14 -04:00
Artem Bilan
90bc65ea49 GH-3866: DefLockRepository: expose query setters (#8606)
Fixes https://github.com/spring-projects/spring-integration/issues/3866

Some RDBMS vendors (or their JDBC drivers) may just log the problem
without throwing an exception.

* Expose setters for UPDATE and INSERTS queries in the `DefaultLockRepository`
to let end-user to modify them respectively, e.g. be able to add a PostgreSQL
`ON CONFLICT DO NOTHING` hint.
* Refactor `DefaultLockRepository` to `Instant` instead of `LocalDateTime`
with zone offset.
* Refactor `ttl` property to `Duration` type
* Fix `dead-lock` typo to `deadlock`
2023-05-01 17:27:20 -04:00
Igor Lovich
e39449b643 GH-8582: Add TX support for PostgresSubChannel
Fixes https://github.com/spring-projects/spring-integration/issues/8582

* Introduce a `PostgresSubscribableChannel.setTransactionManager()`
to wrap a message polling and dispatching operation into a transaction
* In addition add a `RetryTemplate` support around transaction attempts

**Cherry-pick to `6.0.x`**
2023-03-29 12:34:47 -04:00
abilan
22d47e72e9 Use Java text blocks for scripts in code
* Fix `WebServiceInboundGatewayParserTests` for reply timeout for
replies which never come accoridn the test logic
2023-03-28 18:50:34 -04:00
Artem Bilan
1bec420fd1 Do not block by default (#8580)
Currently, many timeouts in the project are like `-1` or other negative value
with a meaning to wait indefinitely.

According to distributed systems design and bad demo developing experience
it is not OK to block forever.

* Rework most of the timeouts in the framework to be `30` seconds.
Only one remained as `1` seconds is a `PollingConsumer` where it is
better to not block even for those 30 seconds when no messages in the queue,
but let the polling task be rescheduled.
* Remove the `MessagingGatewaySupport.replyTimeout` propagation down to the
`PollingConsumer` correlator where it was a `-1` before and blocked
the polling thread on the `Queue.poll()`.
This fixed the problem with a single thread in a pool for auto-configured `TaskScheduler`.
Now with 1 seconds wait time we are able to switch to other scheduled tasks
even with only 1 thread in the pool
2023-03-21 17:43:00 -04: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
abilan
7864658d01 GH-3686: Apply SF editor config
Fixes https://github.com/spring-projects/spring-integration/issues/3686

* Add `src/idea` with respective editor config for IntelliJ IDEA.
Must be imported into an IDE
* Add `src/eclipse` with respective editor config for Eclipse/STS
* Reformat imports in source code according a new editor config
2022-11-14 10:55:21 -05:00
Artem Bilan
d31f309752 More Sonar fixes 2022-11-03 17:28:54 -04:00
Artem Bilan
6284070b45 Some Sonar fixes 2022-11-01 16:29:14 -04:00
Artem Bilan
ef63d90262 Fix some Sonar smells 2022-11-01 12:19:24 -04:00
Artem Bilan
f146b4cbbe Move Spring deps to SNAPSHOTs; other changes
* Removed overridden `getMethodValue()` in the `CookieTests` which is removed from SF already
* Re-enable JDBC tests related to complex named params because of the fix in SF
* `--add-opens` for Tomcat warnings
* Upgrade to `log4j-slf4j2-impl`
* Add `cassandra.yaml` resource with increased timeouts to wait more in busy environment from Cassandra cluster
2022-10-19 14:06:33 -04:00
Artem Bilan
f7dd876be2 INT-3333: Return empty list as is from DB gateway (#3907)
* INT-3333: Return empty list as is from DB gateway

Fixes https://jira.spring.io/browse/INT-3333

In `JdbcOutboundGateway` and `JpaOutboundGateway` the empty result list
is treated as "no reply" and therefore `null` is returned cause
the flow to stop at this point.
It is better to return such a result as is and the target application to
decided what to do with it, e.g. a `discardChannel` on a downstream splitter
configuration.

NOTE: the `MongoDbOutboundGateway` doesn't treat an empty result as a `null`

* * Fix language in docs

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

Co-authored-by: Gary Russell <grussell@vmware.com>
2022-10-11 14:39:29 -04:00
Rafael Winterhalter
14d85977d7 GH-3872: Add PostgresSubscribableChannel implementation
Fixes https://github.com/spring-projects/spring-integration/issues/3872

Adds an implementation for a Postres-compatible notification listener for a `JdbcChannelMessageStore`.

* Introduce `PostgresChannelMessageTableSubscriber.Subscription` contract
* Implement a `PostgresSubscribableChannel`

* Add Javadoc and fix code formatting issues.
* Handle temporary connection loss.
* Add tests for `PostgresChannelMessageTableSubscriber`

* Replace NOTIFY command with pg_notify function call.

* Code style clean up
* Fix some Javadocs
* Use `DataSourceInitializer` in the `PostgresChannelMessageTableSubscriberTests` to populate scripts
* Use Java text block for DB scripts
2022-09-20 16:18:48 -04:00