diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraExceptionTranslator.java b/src/main/java/org/springframework/data/cassandra/core/CassandraExceptionTranslator.java index 9c08e05ac..973375b3c 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraExceptionTranslator.java +++ b/src/main/java/org/springframework/data/cassandra/core/CassandraExceptionTranslator.java @@ -16,37 +16,130 @@ package org.springframework.data.cassandra.core; import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.cassandra.core.exceptions.CassandraAuthenticationException; +import org.springframework.data.cassandra.core.exceptions.CassandraInternalException; +import org.springframework.data.cassandra.core.exceptions.CassandraInvalidConfigurationInQueryException; +import org.springframework.data.cassandra.core.exceptions.CassandraInvalidQueryException; +import org.springframework.data.cassandra.core.exceptions.CassandraTypeMismatchException; +import org.springframework.data.cassandra.core.exceptions.CassandraKeyspaceExistsException; +import org.springframework.data.cassandra.core.exceptions.CassandraConnectionFailureException; +import org.springframework.data.cassandra.core.exceptions.CassandraReadTimeoutException; +import org.springframework.data.cassandra.core.exceptions.CassandraQuerySyntaxException; +import org.springframework.data.cassandra.core.exceptions.CassandraTableExistsException; +import org.springframework.data.cassandra.core.exceptions.CassandraTraceRetrievalException; +import org.springframework.data.cassandra.core.exceptions.CassandraTruncateException; +import org.springframework.data.cassandra.core.exceptions.CassandraUnauthorizedException; +import org.springframework.data.cassandra.core.exceptions.CassandraInsufficientReplicasAvailableException; +import org.springframework.data.cassandra.core.exceptions.CassandraUncategorizedException; +import org.springframework.data.cassandra.core.exceptions.CassandraWriteTimeoutException; +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; /** - * 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. Return {@literal null} if no + * translation is appropriate: any other exception may have resulted from user + * code, and should not be translated. * * @author Alex Shvid + * @author Matthew T. Adams */ -public class CassandraExceptionTranslator implements PersistenceExceptionTranslator { +public class CassandraExceptionTranslator implements + PersistenceExceptionTranslator { /* * (non-Javadoc) - * @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException) + * + * @see org.springframework.dao.support.PersistenceExceptionTranslator# + * translateExceptionIfPossible(java.lang.RuntimeException) */ - public DataAccessException translateExceptionIfPossible(RuntimeException ex) { + public DataAccessException translateExceptionIfPossible(RuntimeException x) { - // Check for well-known Cassandra subclasses. - - if (ex instanceof InvalidQueryException) { - return new DataAccessResourceFailureException(ex.getMessage(), ex); + if (!(x instanceof DriverException)) { + return null; } - - // If we get here, we have an exception that resulted from user code, - // rather than the persistence provider, so we return null to indicate - // that translation should not occur. - 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 (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 (x instanceof InvalidConfigurationInQueryException) { + return new CassandraInvalidConfigurationInQueryException( + x.getMessage(), x); + } + if (x instanceof InvalidQueryException) { + return new CassandraInvalidQueryException(x.getMessage(), x); + } + if (x instanceof SyntaxError) { + return new CassandraQuerySyntaxException(x.getMessage(), x); + } + if (x instanceof UnauthorizedException) { + return new CassandraUnauthorizedException(x.getMessage(), x); + } + if (x instanceof TraceRetrievalException) { + return new CassandraTraceRetrievalException(x.getMessage(), x); + } + + // unknown or unhandled exception + return new CassandraUncategorizedException(x.getMessage(), x); } - } diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java b/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java index 961925dea..17d117f51 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java +++ b/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java @@ -37,7 +37,6 @@ import com.datastax.driver.core.Metadata; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; -import com.datastax.driver.core.exceptions.NoHostAvailableException; /** * @author Alex Shvid @@ -118,8 +117,6 @@ public class CassandraTemplate implements CassandraOperations { public ResultSet executeQuery(String query) { try { return session.execute(query); - } catch (NoHostAvailableException e) { - throw new CassandraConnectionFailureException("no host available", e); } catch (RuntimeException e) { throw potentiallyConvertRuntimeException(e); } @@ -233,8 +230,6 @@ public class CassandraTemplate implements CassandraOperations { result.add(readRowCallback.doWith(row)); } return result; - } catch (NoHostAvailableException e) { - throw new CassandraConnectionFailureException("no host available", e); } catch (RuntimeException e) { throw potentiallyConvertRuntimeException(e); } @@ -253,8 +248,6 @@ public class CassandraTemplate implements CassandraOperations { return result; } return null; - } catch (NoHostAvailableException e) { - throw new CassandraConnectionFailureException("no host available", e); } catch (RuntimeException e) { throw potentiallyConvertRuntimeException(e); } diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraAuthenticationException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraAuthenticationException.java new file mode 100644 index 000000000..833cafcb2 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraAuthenticationException.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import java.net.InetAddress; + +import org.springframework.dao.PermissionDeniedDataAccessException; + +/** + * Spring data access exception for a Cassandra authentication failure. + * + * @author Matthew T. Adams + */ +public class CassandraAuthenticationException extends + PermissionDeniedDataAccessException { + + private static final long serialVersionUID = 8556304586797273927L; + + private InetAddress host; + + public CassandraAuthenticationException(InetAddress host, String msg, + Throwable cause) { + super(msg, cause); + this.host = host; + } + + public InetAddress getHost() { + return host; + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraConnectionFailureException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraConnectionFailureException.java new file mode 100644 index 000000000..ff48523e0 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraConnectionFailureException.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import java.net.InetAddress; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.dao.DataAccessResourceFailureException; + +/** + * Spring data access exception for Cassandra when no host is available. + * + * @author Matthew T. Adams + */ +public class CassandraConnectionFailureException extends + DataAccessResourceFailureException { + + private static final long serialVersionUID = 6299912054261646552L; + + private final Map messagesByHost = new HashMap(); + + public CassandraConnectionFailureException( + Map messagesByHost, String msg, Throwable cause) { + super(msg, cause); + this.messagesByHost.putAll(messagesByHost); + } + + public Map getMessagesByHost() { + return Collections.unmodifiableMap(messagesByHost); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInsufficientReplicasAvailableException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInsufficientReplicasAvailableException.java new file mode 100644 index 000000000..bcd7c70bb --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInsufficientReplicasAvailableException.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.TransientDataAccessException; + +/** + * Spring data access exception for Cassandra when insufficient replicas are + * available for a given consistency level. + * + * @author Matthew T. Adams + */ +public class CassandraInsufficientReplicasAvailableException extends + TransientDataAccessException { + + private static final long serialVersionUID = 6415130674604814905L; + + private int numberRequired; + private int numberAlive; + + public CassandraInsufficientReplicasAvailableException(String msg) { + super(msg); + } + + public CassandraInsufficientReplicasAvailableException(int numberRequired, + int numberAlive, String msg, Throwable cause) { + super(msg, cause); + this.numberRequired = numberRequired; + this.numberAlive = numberAlive; + } + + public int getNumberRequired() { + return numberRequired; + } + + public int getNumberAlive() { + return numberAlive; + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraConnectionFailureException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInternalException.java similarity index 54% rename from src/main/java/org/springframework/data/cassandra/core/CassandraConnectionFailureException.java rename to src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInternalException.java index 194113f93..380ba56e1 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraConnectionFailureException.java +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInternalException.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2010-2013 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. @@ -13,23 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.cassandra.core; -import org.springframework.dao.DataAccessResourceFailureException; +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.DataAccessException; /** - * Cassandra connection exception. + * Spring data access exception for a Cassandra internal error. * - * @author Alex Shvid + * @author Matthew T. Adams */ -public class CassandraConnectionFailureException extends DataAccessResourceFailureException { +public class CassandraInternalException extends DataAccessException { - public CassandraConnectionFailureException(String msg) { + private static final long serialVersionUID = 433061676465346338L; + + public CassandraInternalException(String msg) { super(msg); } - public CassandraConnectionFailureException(String msg, Throwable cause) { + public CassandraInternalException(String msg, Throwable cause) { super(msg, cause); } - } diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInvalidConfigurationInQueryException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInvalidConfigurationInQueryException.java new file mode 100644 index 000000000..00c206f42 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInvalidConfigurationInQueryException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * Spring data access exception for a Cassandra query that is syntactically + * correct but has an invalid configuration clause. + * + * @author Matthew T. Adams + */ +public class CassandraInvalidConfigurationInQueryException extends + InvalidDataAccessApiUsageException { + + private static final long serialVersionUID = 4594321191806182918L; + + public CassandraInvalidConfigurationInQueryException(String msg) { + super(msg); + } + + public CassandraInvalidConfigurationInQueryException(String msg, + Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInvalidQueryException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInvalidQueryException.java new file mode 100644 index 000000000..8f517f652 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInvalidQueryException.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * Spring data access exception for a Cassandra query that's syntactically + * correct but invalid. + * + * @author Matthew T. Adams + */ +public class CassandraInvalidQueryException extends + InvalidDataAccessApiUsageException { + + private static final long serialVersionUID = 4594321191806182918L; + + public CassandraInvalidQueryException(String msg) { + super(msg); + } + + public CassandraInvalidQueryException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraKeyspaceExistsException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraKeyspaceExistsException.java new file mode 100644 index 000000000..edc32dd80 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraKeyspaceExistsException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +/** + * Spring data access exception for Cassandra when a keyspace being created + * already exists. + * + * @author Matthew T. Adams + */ +public class CassandraKeyspaceExistsException extends + CassandraSchemaElementExistsException { + + private static final long serialVersionUID = 6032967419751410352L; + + public CassandraKeyspaceExistsException(String keyspaceName, String msg, + Throwable cause) { + super(keyspaceName, ElementType.KEYSPACE, msg, cause); + } + + public String getKeyspaceName() { + return getElementName(); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraQuerySyntaxException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraQuerySyntaxException.java new file mode 100644 index 000000000..949d550c5 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraQuerySyntaxException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * Spring data access exception for a Cassandra query syntax error. + * + * @author Matthew T. Adams + */ +public class CassandraQuerySyntaxException extends InvalidDataAccessApiUsageException { + + private static final long serialVersionUID = 4398474399882434154L; + + public CassandraQuerySyntaxException(String msg) { + super(msg); + } + + public CassandraQuerySyntaxException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraReadTimeoutException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraReadTimeoutException.java new file mode 100644 index 000000000..76b2d48a0 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraReadTimeoutException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.QueryTimeoutException; + +/** + * Spring data access exception for a Cassandra read timeout. + * + * @author Matthew T. Adams + */ +public class CassandraReadTimeoutException extends QueryTimeoutException { + + private static final long serialVersionUID = -787022307935203387L; + + private boolean wasDataReceived; + + public CassandraReadTimeoutException(boolean wasDataReceived, String msg, + Throwable cause) { + super(msg); + this.wasDataReceived = wasDataReceived; + } + + public boolean getWasDataReceived() { + return wasDataReceived; + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraSchemaElementExistsException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraSchemaElementExistsException.java new file mode 100644 index 000000000..c8b261065 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraSchemaElementExistsException.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.NonTransientDataAccessException; + +/** + * Spring data access exception for when Cassandra schema element being created + * already exists. + * + * @author Matthew T. Adams + */ +public class CassandraSchemaElementExistsException extends + NonTransientDataAccessException { + + private static final long serialVersionUID = 7798361273692300162L; + + public enum ElementType { + KEYSPACE, TABLE, COLUMN, INDEX; + } + + private String elementName; + private ElementType elementType; + + public CassandraSchemaElementExistsException(String elementName, + ElementType elementType, String msg, Throwable cause) { + super(msg, cause); + this.elementName = elementName; + this.elementType = elementType; + } + + public String getElementName() { + return elementName; + } + + public ElementType getElementType() { + return elementType; + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTableExistsException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTableExistsException.java new file mode 100644 index 000000000..1b9307e5c --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTableExistsException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +/** + * Spring data access exception for when a Cassandra table being created already + * exists. + * + * @author Matthew T. Adams + */ +public class CassandraTableExistsException extends + CassandraSchemaElementExistsException { + + private static final long serialVersionUID = 6032967419751410352L; + + public CassandraTableExistsException(String tableName, String msg, + Throwable cause) { + super(tableName, ElementType.TABLE, msg, cause); + } + + public String getTableName() { + return getElementName(); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTraceRetrievalException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTraceRetrievalException.java new file mode 100644 index 000000000..d8cf40f85 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTraceRetrievalException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.TransientDataAccessException; + +/** + * Spring data access exception for a Cassandra trace retrieval exception. + * + * @author Matthew T. Adams + */ +public class CassandraTraceRetrievalException extends + TransientDataAccessException { + + private static final long serialVersionUID = -3163557220324700239L; + + public CassandraTraceRetrievalException(String msg) { + super(msg); + } + + public CassandraTraceRetrievalException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTruncateException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTruncateException.java new file mode 100644 index 000000000..71834c1a7 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTruncateException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.TransientDataAccessException; + +/** + * Spring data access exception for a Cassandra truncate exception. + * + * @author Matthew T. Adams + */ +public class CassandraTruncateException extends TransientDataAccessException { + + private static final long serialVersionUID = 5730642491362430311L; + + public CassandraTruncateException(String msg) { + super(msg); + } + + public CassandraTruncateException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTypeMismatchException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTypeMismatchException.java new file mode 100644 index 000000000..3a6847831 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraTypeMismatchException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.TypeMismatchDataAccessException; + +/** + * Spring data access exception for a Cassandra type mismatch exception. + * + * @author Matthew T. Adams + */ +public class CassandraTypeMismatchException extends + TypeMismatchDataAccessException { + + private static final long serialVersionUID = -7420058975444905629L; + + public CassandraTypeMismatchException(String msg) { + super(msg); + } + + public CassandraTypeMismatchException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraUnauthorizedException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraUnauthorizedException.java new file mode 100644 index 000000000..ad981702d --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraUnauthorizedException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.PermissionDeniedDataAccessException; + +/** + * Spring data access exception for when access to a Cassandra element is + * denied. + * + * @author Matthew T. Adams + */ +public class CassandraUnauthorizedException extends + PermissionDeniedDataAccessException { + + private static final long serialVersionUID = 4618185356687726647L; + + public CassandraUnauthorizedException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraSystemException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraUncategorizedException.java similarity index 65% rename from src/main/java/org/springframework/data/cassandra/core/CassandraSystemException.java rename to src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraUncategorizedException.java index cbbbfc0da..ecab6d54b 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraSystemException.java +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraUncategorizedException.java @@ -13,20 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.cassandra.core; +package org.springframework.data.cassandra.core.exceptions; import org.springframework.dao.UncategorizedDataAccessException; /** - * Exception thrown when we can't classify a Cassandra exception into one of Spring generic data access exceptions. - * + * Spring data access exception for an uncategorized Cassandra exception. + * * @author Alex Shvid + * @author Matthew T. Adams */ +public class CassandraUncategorizedException extends UncategorizedDataAccessException { -public class CassandraSystemException extends UncategorizedDataAccessException { + private static final long serialVersionUID = 1029525121238025444L; - public CassandraSystemException(String msg, Throwable cause) { + public CassandraUncategorizedException(String msg, Throwable cause) { super(msg, cause); } - } diff --git a/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraWriteTimeoutException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraWriteTimeoutException.java new file mode 100644 index 000000000..e35474b68 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraWriteTimeoutException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2013 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.cassandra.core.exceptions; + +import org.springframework.dao.QueryTimeoutException; + +/** + * Spring data access exception for a Cassandra write timeout. + * + * @author Matthew T. Adams + */ +public class CassandraWriteTimeoutException extends QueryTimeoutException { + + private static final long serialVersionUID = -4374826375213670718L; + + private String writeType; + + public CassandraWriteTimeoutException(String writeType, String msg, + Throwable cause) { + super(msg, cause); + this.writeType = writeType; + } + + public String getWriteType() { + return writeType; + } +} diff --git a/src/test/java/org/springframework/data/cassandra/core/CassandraExceptionTranslatorTest.java b/src/test/java/org/springframework/data/cassandra/core/CassandraExceptionTranslatorTest.java new file mode 100644 index 000000000..3ee016a97 --- /dev/null +++ b/src/test/java/org/springframework/data/cassandra/core/CassandraExceptionTranslatorTest.java @@ -0,0 +1,73 @@ +package org.springframework.data.cassandra.core; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.dao.DataAccessException; +import org.springframework.data.cassandra.core.exceptions.CassandraInvalidConfigurationInQueryException; +import org.springframework.data.cassandra.core.exceptions.CassandraInvalidQueryException; +import org.springframework.data.cassandra.core.exceptions.CassandraKeyspaceExistsException; +import org.springframework.data.cassandra.core.exceptions.CassandraSchemaElementExistsException; +import org.springframework.data.cassandra.core.exceptions.CassandraTableExistsException; + +import com.datastax.driver.core.exceptions.AlreadyExistsException; +import com.datastax.driver.core.exceptions.InvalidConfigurationInQueryException; +import com.datastax.driver.core.exceptions.InvalidQueryException; + +public class CassandraExceptionTranslatorTest { + + CassandraExceptionTranslator tx = new CassandraExceptionTranslator(); + + @Test + public void testTableExistsException() { + String keyspace = ""; + String table = "tbl"; + AlreadyExistsException cx = new AlreadyExistsException(keyspace, table); + DataAccessException dax = tx.translateExceptionIfPossible(cx); + assertNotNull(dax); + assertTrue(dax instanceof CassandraTableExistsException); + + CassandraTableExistsException x = (CassandraTableExistsException) dax; + assertEquals(table, x.getTableName()); + assertEquals(x.getTableName(), x.getElementName()); + assertEquals(CassandraSchemaElementExistsException.ElementType.TABLE, + x.getElementType()); + assertEquals(cx, x.getCause()); + } + + @Test + public void testKeyspaceExistsException() { + String keyspace = "ks"; + String table = ""; + AlreadyExistsException cx = new AlreadyExistsException(keyspace, table); + DataAccessException dax = tx.translateExceptionIfPossible(cx); + assertNotNull(dax); + assertTrue(dax instanceof CassandraKeyspaceExistsException); + + CassandraKeyspaceExistsException x = (CassandraKeyspaceExistsException) dax; + assertEquals(keyspace, x.getKeyspaceName()); + assertEquals(x.getKeyspaceName(), x.getElementName()); + assertEquals( + CassandraSchemaElementExistsException.ElementType.KEYSPACE, + x.getElementType()); + assertEquals(cx, x.getCause()); + } + + @Test + public void testInvalidConfigurationInQueryException() { + String msg = "msg"; + InvalidQueryException cx = new InvalidConfigurationInQueryException(msg); + DataAccessException dax = tx.translateExceptionIfPossible(cx); + assertNotNull(dax); + assertTrue(dax instanceof CassandraInvalidConfigurationInQueryException); + assertEquals(cx, dax.getCause()); + + cx = new InvalidQueryException(msg); + dax = tx.translateExceptionIfPossible(cx); + assertNotNull(dax); + assertTrue(dax instanceof CassandraInvalidQueryException); + assertEquals(cx, dax.getCause()); + } +}