diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/JdbcLockRegistry.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/JdbcLockRegistry.java index 8decf8577f..087766aa5f 100644 --- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/JdbcLockRegistry.java +++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/lock/JdbcLockRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 the original author or authors. + * Copyright 2016-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.TransientDataAccessException; import org.springframework.integration.support.locks.ExpirableLockRegistry; import org.springframework.integration.util.UUIDConverter; +import org.springframework.transaction.TransactionSystemException; import org.springframework.transaction.TransactionTimedOutException; import org.springframework.util.Assert; @@ -50,6 +51,7 @@ import org.springframework.util.Assert; * @author Gary Russell * @author Alexandre Strubel * @author Olivier Hubaut + * @author Fran Aranda * * @since 4.3 */ @@ -134,7 +136,7 @@ public class JdbcLockRegistry implements ExpirableLockRegistry { } break; } - catch (TransientDataAccessException | TransactionTimedOutException e) { + catch (TransientDataAccessException | TransactionTimedOutException | TransactionSystemException e) { // try again } catch (InterruptedException e) { @@ -168,7 +170,7 @@ public class JdbcLockRegistry implements ExpirableLockRegistry { } break; } - catch (TransientDataAccessException | TransactionTimedOutException e) { + catch (TransientDataAccessException | TransactionTimedOutException | TransactionSystemException e) { // try again } catch (InterruptedException ie) { @@ -212,7 +214,7 @@ public class JdbcLockRegistry implements ExpirableLockRegistry { } return acquired; } - catch (TransientDataAccessException | TransactionTimedOutException e) { + catch (TransientDataAccessException | TransactionTimedOutException | TransactionSystemException e) { // try again } catch (Exception e) { @@ -245,7 +247,7 @@ public class JdbcLockRegistry implements ExpirableLockRegistry { this.mutex.delete(this.path); return; } - catch (TransientDataAccessException | TransactionTimedOutException e) { + catch (TransientDataAccessException | TransactionTimedOutException | TransactionSystemException e) { // try again } catch (Exception e) { diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDelegateTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDelegateTests.java index 0efebb97f6..e525d19aa3 100644 --- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDelegateTests.java +++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/lock/JdbcLockRegistryDelegateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 the original author or authors. + * Copyright 2020-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,10 +32,12 @@ import org.junit.jupiter.api.Test; import org.springframework.dao.TransientDataAccessException; import org.springframework.integration.test.util.TestUtils; +import org.springframework.transaction.TransactionSystemException; import org.springframework.transaction.TransactionTimedOutException; /** * @author Olivier Hubaut + * @author Fran Aranda * * @since 5.2.11 */ @@ -122,4 +124,22 @@ public class JdbcLockRegistryDelegateTests { assertThat(TestUtils.getPropertyValue(lock, "delegate", ReentrantLock.class).isLocked()).isFalse(); } + @Test + public void testTransactionSystemException() { + final Lock lock = registry.obtain("foo"); + lock.tryLock(); + + final AtomicBoolean shouldThrow = new AtomicBoolean(true); + doAnswer(invocation -> { + if (shouldThrow.getAndSet(false)) { + throw mock(TransactionSystemException.class); + } + return null; + }).when(repository).delete(anyString()); + + lock.unlock(); + + assertThat(TestUtils.getPropertyValue(lock, "delegate", ReentrantLock.class).isLocked()).isFalse(); + } + }