Skip to content

Commit 5875522

Browse files
committed
Throw ConcurrentModificationException if the ownership of a RedisLock/JdbcLock is expired.
1 parent 3187ae5 commit 5875522

File tree

5 files changed

+20
-17
lines changed

5 files changed

+20
-17
lines changed

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.integration.jdbc.lock;
1818

1919
import java.time.Duration;
20+
import java.util.ConcurrentModificationException;
2021
import java.util.LinkedHashMap;
2122
import java.util.Map;
2223
import java.util.Map.Entry;
@@ -349,15 +350,14 @@ public void unlock() {
349350
return;
350351
}
351352
else {
352-
throw new IllegalStateException();
353-
// the lock is no longer owned by current process, the exception should be handle and rollback the execution result
353+
throw new ConcurrentModificationException();
354354
}
355355
}
356356
catch (TransientDataAccessException | TransactionTimedOutException | TransactionSystemException e) {
357357
// try again
358358
}
359-
catch (IllegalStateException e) {
360-
throw new IllegalStateException("Lock was released in the store due to expiration. " +
359+
catch (ConcurrentModificationException e) {
360+
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
361361
"The integrity of data protected by this lock may have been compromised.");
362362
}
363363
catch (Exception e) {

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.integration.jdbc.lock;
1818

1919
import java.util.ArrayList;
20+
import java.util.ConcurrentModificationException;
2021
import java.util.List;
2122
import java.util.concurrent.BlockingQueue;
2223
import java.util.concurrent.Callable;
@@ -315,7 +316,7 @@ public void testOutOfDateLockTaken() throws Exception {
315316
});
316317
assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue();
317318
data.add(2);
318-
assertThatThrownBy(lock1::unlock).isInstanceOf(IllegalStateException.class);
319+
assertThatThrownBy(lock1::unlock).isInstanceOf(ConcurrentModificationException.class);
319320
for (int i = 0; i < 2; i++) {
320321
Integer integer = data.poll(10, TimeUnit.SECONDS);
321322
assertThat(integer).isNotNull();

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.integration.jdbc.lock;
1818

19+
import java.util.ConcurrentModificationException;
1920
import java.util.Map;
2021
import java.util.Queue;
2122
import java.util.concurrent.CountDownLatch;
@@ -501,7 +502,7 @@ public void testTryLockWithCustomTtl() throws Exception {
501502
}
502503

503504
@Test
504-
public void testUnlock_lockStatusIsExpired_lockHasBeenAcquiredByAnotherProcess_DataAccessResourceFailureExceptionWillBeThrown() throws Exception {
505+
public void testUnlock_lockStatusIsExpired_lockHasBeenAcquiredByAnotherProcess_ConcurrentModificationExceptionWillBeThrown() throws Exception {
505506
long ttl = 100;
506507
DefaultLockRepository client1 = new DefaultLockRepository(dataSource);
507508
client1.setApplicationContext(this.context);
@@ -521,14 +522,14 @@ public void testUnlock_lockStatusIsExpired_lockHasBeenAcquiredByAnotherProcess_D
521522
assertThat(lock2.tryLock()).isTrue();
522523
}
523524
finally {
524-
assertThatExceptionOfType(IllegalStateException.class)
525+
assertThatExceptionOfType(ConcurrentModificationException.class)
525526
.isThrownBy(() -> lock1.unlock());
526527
lock2.unlock();
527528
}
528529
}
529530

530531
@Test
531-
public void testUnlock_lockStatusIsExpired_lockDataHasBeenDeleted_IllegalStateExceptionWillBeThrown() throws Exception {
532+
public void testUnlock_lockStatusIsExpired_lockDataHasBeenDeleted_ConcurrentModificationExceptionWillBeThrown() throws Exception {
532533
JdbcLockRegistry registry = new JdbcLockRegistry(client, 100);
533534
Lock lock = registry.obtain("foo");
534535
try {
@@ -537,7 +538,7 @@ public void testUnlock_lockStatusIsExpired_lockDataHasBeenDeleted_IllegalStateEx
537538
client.deleteExpired();
538539
}
539540
finally {
540-
assertThatExceptionOfType(IllegalStateException.class)
541+
assertThatExceptionOfType(ConcurrentModificationException.class)
541542
.isThrownBy(() -> lock.unlock());
542543
}
543544
}

Diff for: spring-integration-redis/src/main/java/org/springframework/integration/redis/util/RedisLockRegistry.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.text.SimpleDateFormat;
2020
import java.util.Collections;
21+
import java.util.ConcurrentModificationException;
2122
import java.util.Date;
2223
import java.util.LinkedHashMap;
2324
import java.util.Map;
@@ -514,12 +515,12 @@ private void removeLockKey() {
514515
return;
515516
}
516517
else if (Boolean.FALSE.equals(unlinkResult)) {
517-
throw new IllegalStateException("Lock was released in the store due to expiration. " +
518+
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
518519
"The integrity of data protected by this lock may have been compromised.");
519520
}
520521
}
521522
if (!removeLockKeyInnerDelete()) {
522-
throw new IllegalStateException("Lock was released in the store due to expiration. " +
523+
throw new ConcurrentModificationException("Lock was released in the store due to expiration. " +
523524
"The integrity of data protected by this lock may have been compromised.");
524525
}
525526
}

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.integration.redis.util;
1818

19+
import java.util.ConcurrentModificationException;
1920
import java.util.List;
2021
import java.util.Map;
2122
import java.util.Queue;
@@ -53,7 +54,6 @@
5354
import org.springframework.integration.test.util.TestUtils;
5455

5556
import static org.assertj.core.api.Assertions.assertThat;
56-
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
5757
import static org.assertj.core.api.Assertions.assertThatNoException;
5858
import static org.assertj.core.api.Assertions.assertThatThrownBy;
5959
import static org.mockito.Mockito.mock;
@@ -162,7 +162,7 @@ void testTryLockWithCustomTtl(RedisLockType testRedisLockType) throws Interrupte
162162

163163
@ParameterizedTest
164164
@EnumSource(RedisLockType.class)
165-
void testUnlock_lockStatusIsExpired_IllegalStateExceptionWillBeThrown(RedisLockType testRedisLockType) throws InterruptedException {
165+
void testUnlock_lockStatusIsExpired_ConcurrentModificationExceptionWillBeThrown(RedisLockType testRedisLockType) throws InterruptedException {
166166
RedisLockRegistry registry = new RedisLockRegistry(redisConnectionFactory, this.registryKey, 100);
167167
registry.setRedisLockType(testRedisLockType);
168168
Lock lock = registry.obtain("foo");
@@ -171,7 +171,7 @@ void testUnlock_lockStatusIsExpired_IllegalStateExceptionWillBeThrown(RedisLockT
171171
Thread.sleep(200);
172172
}
173173
finally {
174-
assertThatThrownBy(lock::unlock).isInstanceOf(IllegalStateException.class);
174+
assertThatThrownBy(lock::unlock).isInstanceOf(ConcurrentModificationException.class);
175175
}
176176
registry.destroy();
177177
}
@@ -459,9 +459,9 @@ void testExceptionOnExpire(RedisLockType testRedisLockType) throws Exception {
459459
Lock lock1 = registry.obtain("foo");
460460
assertThat(lock1.tryLock()).isTrue();
461461
waitForExpire("foo");
462-
assertThatIllegalStateException()
463-
.isThrownBy(lock1::unlock)
464-
.withMessageContaining("Lock was released in the store due to expiration.");
462+
assertThatThrownBy(lock1::unlock)
463+
.isInstanceOf(ConcurrentModificationException.class)
464+
.hasMessageContaining("Lock was released in the store due to expiration.");
465465
registry.destroy();
466466
}
467467

0 commit comments

Comments
 (0)