diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/CassandraDriverTimeOutException.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/CassandraDriverTimeOutException.java new file mode 100644 index 000000000..73b94e711 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/CassandraDriverTimeOutException.java @@ -0,0 +1,15 @@ +package org.springframework.data.cassandra; + +import org.springframework.dao.QueryTimeoutException; + +/** + * This exception is thrown when driver have timed out during any interation with cassandra coordinator node + * + * @author Mikhail Polivakha + */ +public class CassandraDriverTimeOutException extends QueryTimeoutException { + + public CassandraDriverTimeOutException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslator.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslator.java index b0fe6caab..cbdef1105 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslator.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslator.java @@ -23,10 +23,12 @@ import java.util.Set; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.dao.QueryTimeoutException; import org.springframework.dao.TransientDataAccessResourceException; import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.cassandra.CassandraAuthenticationException; import org.springframework.data.cassandra.CassandraConnectionFailureException; +import org.springframework.data.cassandra.CassandraDriverTimeOutException; import org.springframework.data.cassandra.CassandraInsufficientReplicasAvailableException; import org.springframework.data.cassandra.CassandraInvalidConfigurationInQueryException; import org.springframework.data.cassandra.CassandraInvalidQueryException; @@ -43,6 +45,7 @@ import org.springframework.util.StringUtils; import com.datastax.oss.driver.api.core.AllNodesFailedException; import com.datastax.oss.driver.api.core.DriverException; +import com.datastax.oss.driver.api.core.DriverTimeoutException; import com.datastax.oss.driver.api.core.auth.AuthenticationException; import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.servererrors.AlreadyExistsException; @@ -70,6 +73,7 @@ import com.datastax.oss.driver.api.core.servererrors.WriteType; * @author Alex Shvid * @author Matthew T. Adams * @author Mark Paluch + * @author Mikhail Polivakha */ @SuppressWarnings("unchecked") public class CassandraExceptionTranslator implements CqlExceptionTranslator { @@ -105,6 +109,10 @@ public class CassandraExceptionTranslator implements CqlExceptionTranslator { exception); } + if (exception instanceof DriverTimeoutException driverTimeoutException) { + return new CassandraDriverTimeOutException(driverTimeoutException.getMessage(), driverTimeoutException); + } + if (exception instanceof ReadTimeoutException) { return new CassandraReadTimeoutException(((ReadTimeoutException) exception).wasDataPresent(), message, exception); } @@ -178,7 +186,6 @@ public class CassandraExceptionTranslator implements CqlExceptionTranslator { // unknown or unhandled exception return new CassandraUncategorizedException(message, exception); } - return null; } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslatorUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslatorUnitTests.java index e628579f9..adfc15e1c 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslatorUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/cql/CassandraExceptionTranslatorUnitTests.java @@ -28,6 +28,7 @@ import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.TransientDataAccessResourceException; import org.springframework.data.cassandra.CassandraAuthenticationException; import org.springframework.data.cassandra.CassandraConnectionFailureException; +import org.springframework.data.cassandra.CassandraDriverTimeOutException; import org.springframework.data.cassandra.CassandraInsufficientReplicasAvailableException; import org.springframework.data.cassandra.CassandraInvalidConfigurationInQueryException; import org.springframework.data.cassandra.CassandraInvalidQueryException; @@ -40,6 +41,7 @@ import org.springframework.data.cassandra.CassandraUncategorizedException; import org.springframework.data.cassandra.CassandraWriteTimeoutException; import com.datastax.oss.driver.api.core.DefaultConsistencyLevel; +import com.datastax.oss.driver.api.core.DriverTimeoutException; import com.datastax.oss.driver.api.core.NoNodeAvailableException; import com.datastax.oss.driver.api.core.ProtocolVersion; import com.datastax.oss.driver.api.core.UnsupportedProtocolVersionException; @@ -72,6 +74,7 @@ import com.datastax.oss.driver.internal.core.metadata.DefaultEndPoint; * * @author Matthew T. Adams * @author Mark Paluch + * @author Mikhail Polivakha */ class CassandraExceptionTranslatorUnitTests { @@ -117,6 +120,14 @@ class CassandraExceptionTranslatorUnitTests { .hasMessageStartingWith("message").hasCauseInstanceOf(InvalidConfigurationInQueryException.class); } + @Test + void shouldRecognizeDriverTimeoutException() { + DataAccessException dataAccessException = sut.translateExceptionIfPossible(new DriverTimeoutException("message")); + + assertThat(dataAccessException).isInstanceOf(CassandraDriverTimeOutException.class).hasMessageStartingWith("message") + .hasCauseInstanceOf(DriverTimeoutException.class); + } + @Test // DATACASS-402 void shouldTranslateUnauthorizedException() {