Skip to content

Commit 98ff051

Browse files
committed
Updates from feedback
1 parent 2665cd4 commit 98ff051

File tree

8 files changed

+21
-16
lines changed

8 files changed

+21
-16
lines changed

spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/JdbcLockRegistry.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,16 +311,15 @@ public void unlock() {
311311
return;
312312
}
313313
else {
314-
throw new ConcurrentModificationException();
315-
// the lock is no longer owned by current process, the exception should be handle and rollback the execution result
314+
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
315+
"The integrity of data protected by this lock may have been compromised.");
316316
}
317317
}
318318
catch (TransientDataAccessException | TransactionTimedOutException | TransactionSystemException e) {
319319
// try again
320320
}
321321
catch (ConcurrentModificationException e) {
322-
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
323-
"The integrity of data protected by this lock may have been compromised.");
322+
throw e;
324323
}
325324
catch (Exception e) {
326325
throw new DataAccessResourceFailureException("Failed to release mutex at " + this.path, e);

spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDifferentClientTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class JdbcLockRegistryDifferentClientTests {
6767
private JdbcLockRegistry registry;
6868

6969
@Autowired
70-
private DefaultLockRepository client;
70+
private LockRepository client;
7171

7272
@Autowired
7373
private ConfigurableApplicationContext context;
@@ -81,7 +81,6 @@ class JdbcLockRegistryDifferentClientTests {
8181
public void clear() {
8282
this.registry.expireUnusedOlderThan(0);
8383
this.client.close();
84-
this.client.afterPropertiesSet();
8584
this.child = new AnnotationConfigApplicationContext();
8685
this.child.registerBean("childLockRepository", DefaultLockRepository.class, this.dataSource);
8786
this.child.setParent(this.context);

spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryTests-context.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
<bean id="lockClient" class="org.springframework.integration.jdbc.lock.DefaultLockRepository">
2626
<constructor-arg name="dataSource" ref="dataSource"/>
27+
<property name="insertQuery"
28+
value="INSERT INTO INT_LOCK (REGION, LOCK_KEY, CLIENT_ID, CREATED_DATE) VALUES (?, ?, ?, ?)"/>
2729
</bean>
2830

2931
<tx:annotation-driven/>

spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryTests.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,7 @@ void testTwoThreadsDifferentRegistries() throws Exception {
276276
Thread.currentThread().interrupt();
277277
}
278278
finally {
279-
try {
280-
lock2.unlock();
281-
}
282-
catch (ConcurrentModificationException ignored) {
283-
}
284-
279+
lock2.unlock();
285280
latch3.countDown();
286281
}
287282
});
@@ -514,7 +509,7 @@ void noTableThrowsExceptionOnStart() {
514509
}
515510

516511
@Test
517-
void testUnlock_lockStatusIsExpired_lockHasBeenAcquiredByAnotherProcess_ConcurrentModificationExceptionWillBeThrown() throws Exception {
512+
void testUnlockAfterLockStatusHasBeenExpiredAndLockHasBeenAcquiredByAnotherProcess() throws Exception {
518513
int ttl = 100;
519514
DefaultLockRepository client1 = new DefaultLockRepository(dataSource);
520515
client1.setApplicationContext(this.context);
@@ -541,7 +536,7 @@ void testUnlock_lockStatusIsExpired_lockHasBeenAcquiredByAnotherProcess_Concurre
541536
}
542537

543538
@Test
544-
void testUnlock_lockStatusIsExpired_lockDataHasBeenDeleted_ConcurrentModificationExceptionWillBeThrown() throws Exception {
539+
void testUnlockAfterLockStatusHasBeenExpiredAndDeleted() throws Exception {
545540
DefaultLockRepository client = new DefaultLockRepository(dataSource);
546541
client.setApplicationContext(this.context);
547542
client.setTimeToLive(100);

spring-integration-redis/src/test/java/org/springframework/integration/redis/util/RedisLockRegistryTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void testLock(RedisLockType testRedisLockType) {
119119

120120
@ParameterizedTest
121121
@EnumSource(RedisLockType.class)
122-
void testUnlock_lockStatusIsExpired_ConcurrentModificationExceptionWillBeThrown(RedisLockType testRedisLockType) throws InterruptedException {
122+
void testUnlockAfterLockStatusHasBeenExpired(RedisLockType testRedisLockType) throws InterruptedException {
123123
RedisLockRegistry registry = new RedisLockRegistry(redisConnectionFactory, this.registryKey, 100);
124124
registry.setRedisLockType(testRedisLockType);
125125
Lock lock = registry.obtain("foo");

src/reference/antora/modules/ROOT/pages/jdbc/lock-registry.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ For example, an insert query for PostgreSQL hint can be configured like this:
5757
lockRepository.setInsertQuery(lockRepository.getInsertQuery() + " ON CONFLICT DO NOTHING");
5858
----
5959

60+
Starting with version 6.4, the `LockRepository.delete()` method return the result of removing ownership of a distributed lock. And the `JdbcLockRegistry.JdbcLock.unlock()` method throws `ConcurrentModificationException` if the ownership of the lock is expired.

src/reference/antora/modules/ROOT/pages/redis.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,3 +855,5 @@ Default.
855855

856856
The pub-sub is preferred mode - less network chatter between client Redis server, and more performant - the lock is acquired immediately when subscription is notified about unlocking in the other process.
857857
However, the Redis does not support pub-sub in the Master/Replica connections (for example in AWS ElastiCache environment), therefore a busy-spin mode is chosen as a default to make the registry working in any environment.
858+
859+
Starting with version 6.4, instead of throwing `IllegalStateException`, the `RedisLockRegistry.RedisLock.unlock()` method throws `ConcurrentModificationException` if the ownership of the lock is expired.

src/reference/antora/modules/ROOT/pages/whats-new.adoc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ The `LobHandler` (and respective API) has been deprecated for removal in Spring
3232
Respective option on `JdbcMessageStore` (and similar) have been deprecated as well.
3333
The byte array handling for serialized message is fully deferred to JDBC driver.
3434

35+
The `LockRepository.delete()` method return the result of removing ownership of a distributed lock. And the `JdbcLockRegistry.JdbcLock.unlock()` method throws ConcurrentModificationException if the ownership of the lock is expired.
36+
3537
[[x6.4-zeromq-changes]]
3638
=== ZeroMQ Changes
3739

38-
The outbound component `ZeroMqMessageHandler` (and respective API) can now bind a TCP port instead of connecting to a given URL.
40+
The outbound component `ZeroMqMessageHandler` (and respective API) can now bind a TCP port instead of connecting to a given URL.
41+
42+
[[x6.4-redis-changes]]
43+
=== Redis Changes
44+
45+
Instead of throwing `IllegalStateException`, the `RedisLockRegistry.RedisLock.unlock()` method throws `ConcurrentModificationException` if the ownership of the lock is expired.

0 commit comments

Comments
 (0)