diff --git a/gradle.properties b/gradle.properties index 2bfbeeea7..883b974a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ slf4jVersion = 1.6.6 # Common libraries springVersion = 3.1.4.RELEASE -springDataVersion = 1.5.0.RELEASE +springDataVersion = 1.5.3.RELEASE jacksonVersion = 1.8.8 # Testing diff --git a/src/main/java/org/springframework/data/cassandra/config/BeanNames.java b/src/main/java/org/springframework/data/cassandra/config/BeanNames.java index e4c0f9709..f1f9e850f 100644 --- a/src/main/java/org/springframework/data/cassandra/config/BeanNames.java +++ b/src/main/java/org/springframework/data/cassandra/config/BeanNames.java @@ -18,9 +18,9 @@ package org.springframework.data.cassandra.config; /** * @author Alex Shvid */ -public class BeanNames { +public abstract class BeanNames { static final String CASSANDRA_CLUSTER = "cassandra-cluster"; static final String CASSANDRA_KEYSPACE = "cassandra-keyspace"; - + } 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 1a001ef06..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 @@ -99,12 +98,7 @@ public class CassandraTemplate implements CassandraOperations { */ for (Host h: hosts) { - member = new RingMember(); - member.hostName = h.getAddress().getHostName(); - member.address = h.getAddress().getHostAddress(); - member.DC = h.getDatacenter(); - member.rack = h.getRack(); - + member = new RingMember(h); ring.add(member); } @@ -123,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); } @@ -238,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); } @@ -258,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/exceptions/CassandraInternalException.java b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInternalException.java new file mode 100644 index 000000000..380ba56e1 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/exceptions/CassandraInternalException.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.DataAccessException; + +/** + * Spring data access exception for a Cassandra internal error. + * + * @author Matthew T. Adams + */ +public class CassandraInternalException extends DataAccessException { + + private static final long serialVersionUID = 433061676465346338L; + + public CassandraInternalException(String msg) { + super(msg); + } + + 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/main/java/org/springframework/data/cassandra/mapping/CompositeRowId.java b/src/main/java/org/springframework/data/cassandra/mapping/CompositeRowId.java new file mode 100644 index 000000000..954131563 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/mapping/CompositeRowId.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.mapping; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.data.annotation.Id; + +/** + * Identifies composite row ID in the Cassandra table that contains several + * fields. Same as @org.springframework.data.annotation.Id + * + * Example: + * + * class AccountPK { String account; String region; } + * + * @Table class Account { + * @CompositeRowId Account pk; } + * + * + * @author Alex Shvid + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) +@Id +public @interface CompositeRowId { + +} diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraConnectionFailureException.java b/src/main/java/org/springframework/data/cassandra/repository/CassandraRepository.java similarity index 56% rename from src/main/java/org/springframework/data/cassandra/core/CassandraConnectionFailureException.java rename to src/main/java/org/springframework/data/cassandra/repository/CassandraRepository.java index 194113f93..a2c245c6e 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraConnectionFailureException.java +++ b/src/main/java/org/springframework/data/cassandra/repository/CassandraRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2012 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,17 @@ * 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.repository; -import org.springframework.dao.DataAccessResourceFailureException; +import java.io.Serializable; + +import org.springframework.data.repository.CrudRepository; /** - * Cassandra connection exception. + * Cassandra-specific extension of the {@link CrudRepository} interface. * * @author Alex Shvid */ -public class CassandraConnectionFailureException extends DataAccessResourceFailureException { +public interface CassandraRepository extends CrudRepository { - public CassandraConnectionFailureException(String msg) { - super(msg); - } - - public CassandraConnectionFailureException(String msg, Throwable cause) { - super(msg, cause); - } - } diff --git a/src/main/java/org/springframework/data/cassandra/repository/Query.java b/src/main/java/org/springframework/data/cassandra/repository/Query.java new file mode 100644 index 000000000..4098ebbf0 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/repository/Query.java @@ -0,0 +1,42 @@ +/* + * Copyright 2011-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.repository; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to declare finder queries directly on repository methods. + * + * @author Alex Shvid + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Documented +public @interface Query { + + /** + * Takes a Cassandra CQL3 string to define the actual query to be executed. + * + * @return + */ + String value() default ""; + +} diff --git a/src/main/java/org/springframework/data/cassandra/vo/RingMember.java b/src/main/java/org/springframework/data/cassandra/vo/RingMember.java index 8fa56d8c3..19c6429fd 100644 --- a/src/main/java/org/springframework/data/cassandra/vo/RingMember.java +++ b/src/main/java/org/springframework/data/cassandra/vo/RingMember.java @@ -17,21 +17,31 @@ package org.springframework.data.cassandra.vo; import java.io.Serializable; +import com.datastax.driver.core.Host; + /** * @author David Webb * */ -public class RingMember implements Serializable { +public final class RingMember implements Serializable { + + private static final long serialVersionUID = 1345346346L; /* * Ring attributes */ - public String hostName; - public String address; - public String DC; - public String rack; - public String status; - public String state; + public final String hostName; + public final String address; + public final String DC; + public final String rack; + //public final String status; + //public final String state; + public RingMember(Host h) { + this.hostName = h.getAddress().getHostName(); + this.address = h.getAddress().getHostAddress(); + this.DC = h.getDatacenter(); + this.rack = h.getRack(); + } } 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()); + } +}