diff --git a/src/main/java/org/springframework/data/couchbase/core/BucketCallback.java b/src/main/java/org/springframework/data/couchbase/core/BucketCallback.java index a842d331..84e462b5 100644 --- a/src/main/java/org/springframework/data/couchbase/core/BucketCallback.java +++ b/src/main/java/org/springframework/data/couchbase/core/BucketCallback.java @@ -16,9 +16,12 @@ package org.springframework.data.couchbase.core; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + /** * @author Michael Nitschinger */ public interface BucketCallback { - T doInBucket(); + T doInBucket() throws TimeoutException, ExecutionException, InterruptedException; } diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java index 0d73c6ce..3c7945ab 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java @@ -16,9 +16,12 @@ package org.springframework.data.couchbase.core; +import com.couchbase.client.protocol.views.InvalidViewException; +import com.couchbase.client.protocol.views.ViewException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.dao.support.PersistenceExceptionTranslator; import com.couchbase.client.ObservedException; @@ -26,7 +29,8 @@ import com.couchbase.client.ObservedModifiedException; import com.couchbase.client.ObservedTimeoutException; import com.couchbase.client.vbucket.ConnectionException; -import java.io.IOException; +import java.util.concurrent.CancellationException; + /** * Simple {@link PersistenceExceptionTranslator} for Couchbase. @@ -35,6 +39,8 @@ import java.io.IOException; * {@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 Michael Nitschinger */ public class CouchbaseExceptionTranslator implements PersistenceExceptionTranslator { @@ -45,7 +51,8 @@ public class CouchbaseExceptionTranslator implements PersistenceExceptionTransla * @return the translated exception or null. */ @Override - public final DataAccessException translateExceptionIfPossible(RuntimeException ex) { + public final DataAccessException translateExceptionIfPossible(final RuntimeException ex) { + if (ex instanceof ConnectionException) { return new DataAccessResourceFailureException(ex.getMessage(), ex); } @@ -55,6 +62,14 @@ public class CouchbaseExceptionTranslator implements PersistenceExceptionTransla || ex instanceof ObservedModifiedException) { return new DataIntegrityViolationException(ex.getMessage(), ex); } + + if (ex instanceof CancellationException) { + throw new OperationCancellationException(ex.getMessage(), ex); + } + + if (ex instanceof InvalidViewException) { + throw new InvalidDataAccessResourceUsageException(ex.getMessage(), ex); + } return null; } diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java index ca13cfbc..59303620 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java @@ -17,6 +17,8 @@ package org.springframework.data.couchbase.core; import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; import com.couchbase.client.protocol.views.Query; import com.couchbase.client.protocol.views.View; @@ -24,6 +26,7 @@ import com.couchbase.client.protocol.views.ViewResponse; import com.couchbase.client.protocol.views.ViewRow; import net.spy.memcached.internal.OperationFuture; +import org.springframework.dao.QueryTimeoutException; import org.springframework.data.couchbase.core.convert.CouchbaseConverter; import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter; import org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService; @@ -91,11 +94,10 @@ public class CouchbaseTemplate implements CouchbaseOperations { final CouchbaseDocument converted = new CouchbaseDocument(); couchbaseConverter.write(objectToSave, converted); - execute(new BucketCallback>() { + execute(new BucketCallback() { @Override - public OperationFuture doInBucket() { - return client.add( - converted.getId(), converted.getExpiration(), translateEncode(converted)); + public Boolean doInBucket() throws InterruptedException, ExecutionException { + return client.add(converted.getId(), converted.getExpiration(), translateEncode(converted)).get(); } }); } @@ -113,11 +115,10 @@ public class CouchbaseTemplate implements CouchbaseOperations { final CouchbaseDocument converted = new CouchbaseDocument(); couchbaseConverter.write(objectToSave, converted); - execute(new BucketCallback>() { + execute(new BucketCallback() { @Override - public OperationFuture doInBucket() { - return client.set( - converted.getId(), converted.getExpiration(), translateEncode(converted)); + public Boolean doInBucket() throws InterruptedException, ExecutionException { + return client.set(converted.getId(), converted.getExpiration(), translateEncode(converted)).get(); } }); } @@ -135,11 +136,10 @@ public class CouchbaseTemplate implements CouchbaseOperations { final CouchbaseDocument converted = new CouchbaseDocument(); couchbaseConverter.write(objectToSave, converted); - execute(new BucketCallback>() { + execute(new BucketCallback() { @Override - public OperationFuture doInBucket() { - return client.replace( - converted.getId(), converted.getExpiration(), translateEncode(converted)); + public Boolean doInBucket() throws InterruptedException, ExecutionException { + return client.replace(converted.getId(), converted.getExpiration(), translateEncode(converted)).get(); } }); @@ -208,10 +208,10 @@ public class CouchbaseTemplate implements CouchbaseOperations { ensureNotIterable(objectToRemove); if (objectToRemove instanceof String) { - execute(new BucketCallback>() { + execute(new BucketCallback() { @Override - public OperationFuture doInBucket() { - return client.delete((String) objectToRemove); + public Boolean doInBucket() throws InterruptedException, ExecutionException { + return client.delete((String) objectToRemove).get(); } }); return; @@ -235,11 +235,18 @@ public class CouchbaseTemplate implements CouchbaseOperations { } } + @Override public T execute(final BucketCallback action) { try { return action.doInBucket(); } catch (RuntimeException e) { throw potentiallyConvertRuntimeException(e); + } catch (TimeoutException e) { + throw new QueryTimeoutException(e.getMessage(), e); + } catch (InterruptedException e) { + throw new OperationInterruptedException(e.getMessage(), e); + } catch (ExecutionException e) { + throw new OperationInterruptedException(e.getMessage(), e); } } diff --git a/src/main/java/org/springframework/data/couchbase/core/OperationCancellationException.java b/src/main/java/org/springframework/data/couchbase/core/OperationCancellationException.java new file mode 100644 index 00000000..e6ec92b3 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/OperationCancellationException.java @@ -0,0 +1,46 @@ +/* + * Copyright 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.couchbase.core; + +import org.springframework.dao.TransientDataAccessException; + +/** + * Data Access Exception that identifies Operations cancelled while being + * processed. + * + * @author Michael Nitschinger + */ +public class OperationCancellationException extends TransientDataAccessException { + + /** + * Constructor for OperationCancellationException. + * @param msg the detail message + */ + public OperationCancellationException(final String msg) { + super(msg); + } + + /** + * Constructor for OperationCancellationException. + * @param msg the detail message + * @param cause the root cause from the data access API in use + */ + public OperationCancellationException(final String msg, final Throwable cause) { + super(msg, cause); + } + +} diff --git a/src/main/java/org/springframework/data/couchbase/core/OperationInterruptedException.java b/src/main/java/org/springframework/data/couchbase/core/OperationInterruptedException.java new file mode 100644 index 00000000..add1f4b1 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/core/OperationInterruptedException.java @@ -0,0 +1,46 @@ +/* + * Copyright 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.couchbase.core; + +import org.springframework.dao.TransientDataAccessException; + +/** + * Data Access Exception that identifies Operations interrupted while being + * processed. + * + * @author Michael Nitschinger + */ +public class OperationInterruptedException extends TransientDataAccessException { + + /** + * Constructor for OperationInterruptedException. + * @param msg the detail message + */ + public OperationInterruptedException(final String msg) { + super(msg); + } + + /** + * Constructor for OperationInterruptedException. + * @param msg the detail message + * @param cause the root cause from the data access API in use + */ + public OperationInterruptedException(final String msg, final Throwable cause) { + super(msg, cause); + } + +}