diff --git a/spring-cql/src/main/java/org/springframework/cassandra/support/CassandraExceptionTranslator.java b/spring-cql/src/main/java/org/springframework/cassandra/support/CassandraExceptionTranslator.java
index 3872a4c41..b546b83ac 100644
--- a/spring-cql/src/main/java/org/springframework/cassandra/support/CassandraExceptionTranslator.java
+++ b/spring-cql/src/main/java/org/springframework/cassandra/support/CassandraExceptionTranslator.java
@@ -1,12 +1,12 @@
/*
- * Copyright 2013-2014 the original author or authors.
- *
+ * Copyright 2013-2017 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.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -15,117 +15,155 @@
*/
package org.springframework.cassandra.support;
-import org.springframework.cassandra.support.exception.CassandraAuthenticationException;
-import org.springframework.cassandra.support.exception.CassandraConnectionFailureException;
-import org.springframework.cassandra.support.exception.CassandraInsufficientReplicasAvailableException;
-import org.springframework.cassandra.support.exception.CassandraInternalException;
-import org.springframework.cassandra.support.exception.CassandraInvalidConfigurationInQueryException;
-import org.springframework.cassandra.support.exception.CassandraInvalidQueryException;
-import org.springframework.cassandra.support.exception.CassandraKeyspaceExistsException;
-import org.springframework.cassandra.support.exception.CassandraQuerySyntaxException;
-import org.springframework.cassandra.support.exception.CassandraReadTimeoutException;
-import org.springframework.cassandra.support.exception.CassandraTableExistsException;
-import org.springframework.cassandra.support.exception.CassandraTraceRetrievalException;
-import org.springframework.cassandra.support.exception.CassandraTruncateException;
-import org.springframework.cassandra.support.exception.CassandraTypeMismatchException;
-import org.springframework.cassandra.support.exception.CassandraUnauthorizedException;
-import org.springframework.cassandra.support.exception.CassandraUncategorizedException;
-import org.springframework.cassandra.support.exception.CassandraWriteTimeoutException;
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.cassandra.support.exception.*;
import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
+import org.springframework.util.ClassUtils;
import com.datastax.driver.core.WriteType;
-import com.datastax.driver.core.exceptions.AlreadyExistsException;
-import com.datastax.driver.core.exceptions.AuthenticationException;
-import com.datastax.driver.core.exceptions.DriverException;
-import com.datastax.driver.core.exceptions.DriverInternalError;
-import com.datastax.driver.core.exceptions.InvalidConfigurationInQueryException;
-import com.datastax.driver.core.exceptions.InvalidQueryException;
-import com.datastax.driver.core.exceptions.InvalidTypeException;
-import com.datastax.driver.core.exceptions.NoHostAvailableException;
-import com.datastax.driver.core.exceptions.ReadTimeoutException;
-import com.datastax.driver.core.exceptions.SyntaxError;
-import com.datastax.driver.core.exceptions.TraceRetrievalException;
-import com.datastax.driver.core.exceptions.TruncateException;
-import com.datastax.driver.core.exceptions.UnauthorizedException;
-import com.datastax.driver.core.exceptions.UnavailableException;
-import com.datastax.driver.core.exceptions.WriteTimeoutException;
+import com.datastax.driver.core.exceptions.*;
/**
- * Simple {@link PersistenceExceptionTranslator} for Cassandra. Convert the given runtime exception to an appropriate
- * exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
- * appropriate: any other exception may have resulted from user code, and should not be translated.
- *
+ * Simple {@link PersistenceExceptionTranslator} for Cassandra.
+ *
+ * Convert the given runtime exception to an appropriate exception from the {@code org.springframework.dao} hierarchy.
+ * Preserves exception if it's already a {@link DataAccessException} and ignores non {@link DriverException}s returning
+ * {@literal null}. Falls back to {@link CassandraUncategorizedException} in case there's no mapping to a more detailed
+ * exception.
+ *
* @author Alex Shvid
* @author Matthew T. Adams
+ * @author Mark Paluch
*/
-
+@SuppressWarnings("unchecked")
public class CassandraExceptionTranslator implements PersistenceExceptionTranslator {
- @Override
- public DataAccessException translateExceptionIfPossible(RuntimeException x) {
+ private static final Set CONNECTION_FAILURE_TYPES = new HashSet(
+ Arrays.asList("NoHostAvailableException", "ConnectionException", "OperationTimedOutException",
+ "TransportException", "BusyConnectionException", "BusyPoolException"));
- if (x instanceof DataAccessException) {
- return (DataAccessException) x;
+ private static final Set RESOURCE_FAILURE_TYPES = new HashSet(
+ Arrays.asList("ReadFailureException", "WriteFailureException", "FunctionExecutionException"));
+
+ /* (non-Javadoc)
+ * @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
+ */
+ @Override
+ public DataAccessException translateExceptionIfPossible(RuntimeException exception) {
+
+ if (exception instanceof DataAccessException) {
+ return (DataAccessException) exception;
}
- if (!(x instanceof DriverException)) {
+ if (!(exception instanceof DriverException)) {
return null;
}
// Remember: subclasses must come before superclasses, otherwise the
// superclass would match before the subclass!
- if (x instanceof AuthenticationException) {
- return new CassandraAuthenticationException(((AuthenticationException) x).getHost(), x.getMessage(), x);
+ if (exception instanceof AuthenticationException) {
+ return new CassandraAuthenticationException(((AuthenticationException) exception).getHost(),
+ exception.getMessage(), exception);
}
- if (x instanceof DriverInternalError) {
- return new CassandraInternalException(x.getMessage(), x);
- }
- if (x instanceof InvalidTypeException) {
- return new CassandraTypeMismatchException(x.getMessage(), x);
- }
- if (x instanceof NoHostAvailableException) {
- return new CassandraConnectionFailureException(((NoHostAvailableException) x).getErrors(), x.getMessage(), x);
- }
- if (x instanceof ReadTimeoutException) {
- return new CassandraReadTimeoutException(((ReadTimeoutException) x).wasDataRetrieved(), x.getMessage(), x);
- }
- if (x instanceof WriteTimeoutException) {
- WriteType writeType = ((WriteTimeoutException) x).getWriteType();
- return new CassandraWriteTimeoutException(writeType == null ? null : writeType.name(), x.getMessage(), x);
- }
- if (x instanceof TruncateException) {
- return new CassandraTruncateException(x.getMessage(), x);
- }
- if (x instanceof UnavailableException) {
- UnavailableException ux = (UnavailableException) x;
- return new CassandraInsufficientReplicasAvailableException(ux.getRequiredReplicas(), ux.getAliveReplicas(),
- x.getMessage(), x);
- }
- if (x instanceof AlreadyExistsException) {
- AlreadyExistsException aex = (AlreadyExistsException) x;
- return aex.wasTableCreation() ? new CassandraTableExistsException(aex.getTable(), x.getMessage(), x)
- : new CassandraKeyspaceExistsException(aex.getKeyspace(), x.getMessage(), x);
+ if (exception instanceof DriverInternalError) {
+ return new CassandraInternalException(exception.getMessage(), exception);
}
- if (x instanceof InvalidConfigurationInQueryException) {
- return new CassandraInvalidConfigurationInQueryException(x.getMessage(), x);
+
+ if (exception instanceof InvalidTypeException) {
+ return new CassandraTypeMismatchException(exception.getMessage(), exception);
}
- if (x instanceof InvalidQueryException) {
- return new CassandraInvalidQueryException(x.getMessage(), x);
+
+ if (exception instanceof ReadTimeoutException) {
+ return new CassandraReadTimeoutException(((ReadTimeoutException) exception).wasDataRetrieved(),
+ exception.getMessage(), exception);
}
- if (x instanceof SyntaxError) {
- return new CassandraQuerySyntaxException(x.getMessage(), x);
+
+ if (exception instanceof WriteTimeoutException) {
+
+ WriteType writeType = ((WriteTimeoutException) exception).getWriteType();
+ return new CassandraWriteTimeoutException(writeType == null ? null : writeType.name(), exception.getMessage(),
+ exception);
}
- if (x instanceof UnauthorizedException) {
- return new CassandraUnauthorizedException(x.getMessage(), x);
+
+ if (exception instanceof TruncateException) {
+ return new CassandraTruncateException(exception.getMessage(), exception);
}
- if (x instanceof TraceRetrievalException) {
- return new CassandraTraceRetrievalException(x.getMessage(), x);
+
+ if (exception instanceof UnavailableException) {
+
+ UnavailableException ux = (UnavailableException) exception;
+ return new CassandraInsufficientReplicasAvailableException(ux.getRequiredReplicas(), ux.getAliveReplicas(),
+ exception.getMessage(), exception);
+ }
+
+ if (exception instanceof OverloadedException || exception instanceof BootstrappingException) {
+ return new TransientDataAccessResourceException(exception.getMessage(), exception);
+ }
+
+ if (exception instanceof AlreadyExistsException) {
+
+ AlreadyExistsException aex = (AlreadyExistsException) exception;
+
+ return aex.wasTableCreation()
+ ? new CassandraTableExistsException(aex.getTable(), exception.getMessage(), exception)
+ : new CassandraKeyspaceExistsException(aex.getKeyspace(), exception.getMessage(), exception);
+ }
+
+ if (exception instanceof InvalidConfigurationInQueryException) {
+ return new CassandraInvalidConfigurationInQueryException(exception.getMessage(), exception);
+ }
+
+ if (exception instanceof InvalidQueryException) {
+ return new CassandraInvalidQueryException(exception.getMessage(), exception);
+ }
+
+ if (exception instanceof SyntaxError) {
+ return new CassandraQuerySyntaxException(exception.getMessage(), exception);
+ }
+
+ if (exception instanceof UnauthorizedException) {
+ return new CassandraUnauthorizedException(exception.getMessage(), exception);
+ }
+
+ if (exception instanceof TraceRetrievalException) {
+ return new CassandraTraceRetrievalException(exception.getMessage(), exception);
+ }
+
+ if (exception instanceof NoHostAvailableException) {
+ return new CassandraConnectionFailureException(((NoHostAvailableException) exception).getErrors(),
+ exception.getMessage(), exception);
+ }
+
+ String exceptionType = ClassUtils.getShortName(ClassUtils.getUserClass(exception.getClass()));
+
+ if (CONNECTION_FAILURE_TYPES.contains(exceptionType)) {
+
+ Map errorMap = Collections.emptyMap();
+
+ if (exception instanceof CoordinatorException) {
+ CoordinatorException cx = (CoordinatorException) exception;
+ errorMap = Collections. singletonMap(cx.getAddress(), exception);
+ }
+
+ return new CassandraConnectionFailureException(errorMap, exception.getMessage(), exception);
+ }
+
+ if (RESOURCE_FAILURE_TYPES.contains(exceptionType)) {
+ return new DataAccessResourceFailureException(exception.getMessage(), exception);
}
// unknown or unhandled exception
- return new CassandraUncategorizedException(x.getMessage(), x);
+ return new CassandraUncategorizedException(exception.getMessage(), exception);
}
}
diff --git a/spring-cql/src/test/java/org/springframework/cassandra/support/CassandraExceptionTranslatorTest.java b/spring-cql/src/test/java/org/springframework/cassandra/support/CassandraExceptionTranslatorTest.java
index 6478c1af9..b5403a214 100755
--- a/spring-cql/src/test/java/org/springframework/cassandra/support/CassandraExceptionTranslatorTest.java
+++ b/spring-cql/src/test/java/org/springframework/cassandra/support/CassandraExceptionTranslatorTest.java
@@ -16,73 +16,322 @@
package org.springframework.cassandra.support;
import static org.assertj.core.api.Assertions.*;
+import static org.junit.Assume.*;
+
+import java.lang.reflect.Constructor;
+import java.net.InetSocketAddress;
+import java.util.Collections;
import org.junit.Test;
-import org.springframework.cassandra.support.exception.CassandraInvalidConfigurationInQueryException;
-import org.springframework.cassandra.support.exception.CassandraInvalidQueryException;
-import org.springframework.cassandra.support.exception.CassandraKeyspaceExistsException;
-import org.springframework.cassandra.support.exception.CassandraSchemaElementExistsException;
-import org.springframework.cassandra.support.exception.CassandraTableExistsException;
+import org.springframework.cassandra.support.exception.*;
+import org.springframework.cassandra.support.exception.CassandraSchemaElementExistsException.ElementType;
import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataAccessResourceFailureException;
+import org.springframework.dao.TransientDataAccessResourceException;
+import org.springframework.util.ClassUtils;
-import com.datastax.driver.core.exceptions.AlreadyExistsException;
-import com.datastax.driver.core.exceptions.InvalidConfigurationInQueryException;
-import com.datastax.driver.core.exceptions.InvalidQueryException;
+import com.datastax.driver.core.ConsistencyLevel;
+import com.datastax.driver.core.DataType;
+import com.datastax.driver.core.ProtocolVersion;
+import com.datastax.driver.core.WriteType;
+import com.datastax.driver.core.exceptions.*;
+import com.google.common.reflect.TypeToken;
/**
* Unit tests for {@link CassandraExceptionTranslator}
*
* @author Matthew T. Adams
+ * @author Mark Paluch
*/
public class CassandraExceptionTranslatorTest {
- CassandraExceptionTranslator tx = new CassandraExceptionTranslator();
+ InetSocketAddress socketAddress = new InetSocketAddress("localhost", 42);
+ CassandraExceptionTranslator sut = new CassandraExceptionTranslator();
- @Test
- public void testTableExistsException() {
- String keyspace = "";
- String table = "tbl";
- AlreadyExistsException cx = new AlreadyExistsException(keyspace, table);
- DataAccessException dax = tx.translateExceptionIfPossible(cx);
- assertThat(dax).isNotNull();
- assertThat(dax instanceof CassandraTableExistsException).isTrue();
+ @Test // DATACASS-402
+ public void shouldTranslateAuthenticationException() {
- CassandraTableExistsException x = (CassandraTableExistsException) dax;
- assertThat(x.getTableName()).isEqualTo(table);
- assertThat(x.getElementName()).isEqualTo(x.getTableName());
- assertThat(x.getElementType()).isEqualTo(CassandraSchemaElementExistsException.ElementType.TABLE);
- assertThat(x.getCause()).isEqualTo(cx);
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new AuthenticationException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraAuthenticationException.class)
+ .hasMessageStartingWith("Authentication error on host").hasCauseInstanceOf(AuthenticationException.class);
}
- @Test
- public void testKeyspaceExistsException() {
- String keyspace = "ks";
- String table = "";
- AlreadyExistsException cx = new AlreadyExistsException(keyspace, table);
- DataAccessException dax = tx.translateExceptionIfPossible(cx);
- assertThat(dax).isNotNull();
- assertThat(dax instanceof CassandraKeyspaceExistsException).isTrue();
+ @Test // DATACASS-402
+ public void shouldTranslateCassandraInternalException() {
- CassandraKeyspaceExistsException x = (CassandraKeyspaceExistsException) dax;
- assertThat(x.getKeyspaceName()).isEqualTo(keyspace);
- assertThat(x.getElementName()).isEqualTo(x.getKeyspaceName());
- assertThat(x.getElementType()).isEqualTo(CassandraSchemaElementExistsException.ElementType.KEYSPACE);
- assertThat(x.getCause()).isEqualTo(cx);
+ DataAccessException result = sut.translateExceptionIfPossible(new DriverInternalError("message"));
+
+ assertThat(result).isInstanceOf(CassandraInternalException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(DriverInternalError.class);
}
- @Test
- public void testInvalidConfigurationInQueryException() {
- String msg = "msg";
- InvalidQueryException cx = new InvalidConfigurationInQueryException(null, msg);
- DataAccessException dax = tx.translateExceptionIfPossible(cx);
- assertThat(dax).isNotNull();
- assertThat(dax instanceof CassandraInvalidConfigurationInQueryException).isTrue();
- assertThat(dax.getCause()).isEqualTo(cx);
+ @Test // DATACASS-402
+ public void shouldTranslateTraceRetrievalException() {
- cx = new InvalidQueryException(msg);
- dax = tx.translateExceptionIfPossible(cx);
- assertThat(dax).isNotNull();
- assertThat(dax instanceof CassandraInvalidQueryException).isTrue();
- assertThat(dax.getCause()).isEqualTo(cx);
+ DataAccessException result = sut.translateExceptionIfPossible(new TraceRetrievalException("message"));
+
+ assertThat(result).isInstanceOf(CassandraTraceRetrievalException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(TraceRetrievalException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateNoHostAvailableException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(
+ new NoHostAvailableException(Collections.singletonMap(socketAddress, (Throwable) new IllegalStateException())));
+
+ assertThat(result).isInstanceOf(CassandraConnectionFailureException.class)
+ .hasMessageStartingWith("All host(s) tried").hasCauseInstanceOf(NoHostAvailableException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateInvalidQueryException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new InvalidQueryException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraInvalidQueryException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(InvalidQueryException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateInvalidConfigurationInQueryException() {
+
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new InvalidConfigurationInQueryException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraInvalidConfigurationInQueryException.class)
+ .hasMessageStartingWith("message").hasCauseInstanceOf(InvalidConfigurationInQueryException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateUnauthorizedException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new UnauthorizedException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraUnauthorizedException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(UnauthorizedException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateSyntaxError() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new SyntaxError(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraQuerySyntaxException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(SyntaxError.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateKeyspaceExistsException() {
+
+ AlreadyExistsException cx = new AlreadyExistsException("keyspace", "");
+ DataAccessException result = sut.translateExceptionIfPossible(cx);
+
+ assertThat(result).isInstanceOf(CassandraKeyspaceExistsException.class)
+ .hasMessageStartingWith("Keyspace keyspace already exists").hasCauseInstanceOf(AlreadyExistsException.class);
+
+ CassandraSchemaElementExistsException exception = (CassandraSchemaElementExistsException) result;
+
+ assertThat(exception.getElementName()).isEqualTo("keyspace");
+ assertThat(exception.getElementType()).isEqualTo(ElementType.KEYSPACE);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateTableExistsException() {
+
+ AlreadyExistsException cx = new AlreadyExistsException("keyspace", "table");
+ DataAccessException result = sut.translateExceptionIfPossible(cx);
+
+ assertThat(result).isInstanceOf(CassandraTableExistsException.class)
+ .hasMessageStartingWith("Table keyspace.table already exists").hasCauseInstanceOf(AlreadyExistsException.class);
+
+ CassandraSchemaElementExistsException exception = (CassandraSchemaElementExistsException) result;
+
+ assertThat(exception.getElementName()).isEqualTo("table");
+ assertThat(exception.getElementType()).isEqualTo(ElementType.TABLE);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateInvalidTypeException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new InvalidTypeException("message"));
+
+ assertThat(result).isInstanceOf(CassandraTypeMismatchException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(InvalidTypeException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateUnavailableException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new UnavailableException(ConsistencyLevel.ALL, 5, 1));
+
+ assertThat(result).isInstanceOf(CassandraInsufficientReplicasAvailableException.class)
+ .hasMessageStartingWith("Not enough replicas available").hasCauseInstanceOf(UnavailableException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateBootstrappingException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new BootstrappingException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(TransientDataAccessResourceException.class).hasMessageStartingWith("Queried host")
+ .hasCauseInstanceOf(BootstrappingException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateOverloadedException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new OverloadedException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(TransientDataAccessResourceException.class).hasMessageStartingWith("Queried host")
+ .hasCauseInstanceOf(OverloadedException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateTruncateException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new TruncateException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraTruncateException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(TruncateException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateWriteFailureException() {
+
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new WriteFailureException(ConsistencyLevel.ALL, WriteType.BATCH, 1, 5, 1));
+
+ assertThat(result).isInstanceOf(DataAccessResourceFailureException.class)
+ .hasMessageStartingWith("Cassandra failure during").hasCauseInstanceOf(WriteFailureException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateReadFailureException() {
+
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new ReadFailureException(ConsistencyLevel.ALL, 1, 5, 1, true));
+
+ assertThat(result).isInstanceOf(DataAccessResourceFailureException.class)
+ .hasMessageStartingWith("Cassandra failure during").hasCauseInstanceOf(ReadFailureException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateWriteTimeoutException() {
+
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new WriteTimeoutException(ConsistencyLevel.ALL, WriteType.BATCH, 1, 5));
+
+ assertThat(result).isInstanceOf(CassandraWriteTimeoutException.class)
+ .hasMessageStartingWith("Cassandra timeout during").hasCauseInstanceOf(WriteTimeoutException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateReadTimeoutException() {
+
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new ReadTimeoutException(ConsistencyLevel.ALL, 1, 5, true));
+
+ assertThat(result).isInstanceOf(CassandraReadTimeoutException.class)
+ .hasMessageStartingWith("Cassandra timeout during").hasCauseInstanceOf(ReadTimeoutException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateFunctionExecutionException() {
+
+ DataAccessException result = sut
+ .translateExceptionIfPossible(new FunctionExecutionException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(DataAccessResourceFailureException.class).hasMessageStartingWith("message")
+ .hasCauseInstanceOf(FunctionExecutionException.class);
+ }
+
+ @Test // DATACASS-402
+ @SuppressWarnings("unchecked")
+ public void shouldTranslateBusyPoolException() throws Exception {
+
+ assumeTrue(
+ ClassUtils.isPresent("com.datastax.driver.core.exceptions.BusyPoolException", getClass().getClassLoader()));
+
+ DriverException exception = createInstance("com.datastax.driver.core.exceptions.BusyPoolException",
+ new Class[] { InetSocketAddress.class, Integer.TYPE }, socketAddress, 5);
+
+ DataAccessException result = sut.translateExceptionIfPossible(exception);
+
+ assertThat(result).isInstanceOf(CassandraConnectionFailureException.class).hasMessageContaining("Pool is busy")
+ .hasCauseInstanceOf(exception.getClass());
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateConnectionException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new ConnectionException(socketAddress, "message"));
+
+ assertThat(result).isInstanceOf(CassandraConnectionFailureException.class).hasMessageContaining("] message")
+ .hasCauseInstanceOf(ConnectionException.class);
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateBusyConnectionException() {
+
+ DataAccessException result = sut.translateExceptionIfPossible(new BusyConnectionException(socketAddress));
+
+ assertThat(result).isInstanceOf(CassandraConnectionFailureException.class)
+ .hasMessageContaining("Connection has run out of stream").hasCauseInstanceOf(BusyConnectionException.class);
+ }
+
+ @Test // DATACASS-402
+ @SuppressWarnings("unchecked")
+ public void shouldTranslateFrameTooLongException() throws Exception {
+
+ assumeTrue(
+ ClassUtils.isPresent("com.datastax.driver.core.exceptions.FrameTooLongException", getClass().getClassLoader()));
+
+ DriverException exception = createInstance("com.datastax.driver.core.exceptions.FrameTooLongException",
+ new Class[] { Integer.TYPE }, 5);
+
+ DataAccessException result = sut.translateExceptionIfPossible(exception);
+
+ assertThat(result).isInstanceOf(CassandraUncategorizedException.class).hasCauseInstanceOf(exception.getClass());
+ }
+
+ @Test // DATACASS-402
+ public void shouldTranslateToUncategorized() {
+
+ assertThat(sut.translateExceptionIfPossible(
+ new CodecNotFoundException("message", DataType.ascii(), TypeToken.of(Class.class))))
+ .isInstanceOf(CassandraUncategorizedException.class);
+
+ assertThat(sut.translateExceptionIfPossible(
+ new UnsupportedProtocolVersionException(socketAddress, ProtocolVersion.NEWEST_SUPPORTED, ProtocolVersion.V1)))
+ .isInstanceOf(CassandraUncategorizedException.class);
+
+ assertThat(sut.translateExceptionIfPossible(new UnpreparedException(socketAddress, "message")))
+ .isInstanceOf(CassandraUncategorizedException.class);
+
+ assertThat(sut.translateExceptionIfPossible(new PagingStateException("message")))
+ .isInstanceOf(CassandraUncategorizedException.class);
+
+ assertThat(sut.translateExceptionIfPossible(new UnresolvedUserTypeException("keyspace", "message")))
+ .isInstanceOf(CassandraUncategorizedException.class);
+
+ assertThat(
+ sut.translateExceptionIfPossible(new UnsupportedFeatureException(ProtocolVersion.NEWEST_SUPPORTED, "message")))
+ .isInstanceOf(CassandraUncategorizedException.class);
+
+ assertThat(sut.translateExceptionIfPossible(new UnresolvedUserTypeException("keyspace", "message")))
+ .isInstanceOf(CassandraUncategorizedException.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T createInstance(String className, Class> argTypes[], Object... args)
+ throws ReflectiveOperationException {
+
+ Class exceptionClass = (Class) ClassUtils.forName(className, getClass().getClassLoader());
+ Constructor constructor = exceptionClass.getDeclaredConstructor(argTypes);
+
+ return constructor.newInstance(args);
}
}