Skip to content

Commit

Permalink
DATACOUCH-17 - Make ops sync & map exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
daschl committed Jul 16, 2013
1 parent 2eedc4b commit dd9c3ed
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 18 deletions.
Expand Up @@ -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> {
T doInBucket();
T doInBucket() throws TimeoutException, ExecutionException, InterruptedException;
}
Expand Up @@ -16,17 +16,21 @@

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;
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.
Expand All @@ -35,6 +39,8 @@
* {@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 {

Expand All @@ -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);
}
Expand All @@ -55,6 +62,14 @@ public final DataAccessException translateExceptionIfPossible(RuntimeException e
|| 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;
}
Expand Down
Expand Up @@ -17,13 +17,16 @@
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;
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;
Expand Down Expand Up @@ -91,11 +94,10 @@ public final void insert(final Object objectToSave) {
final CouchbaseDocument converted = new CouchbaseDocument();
couchbaseConverter.write(objectToSave, converted);

execute(new BucketCallback<OperationFuture<Boolean>>() {
execute(new BucketCallback<Boolean>() {
@Override
public OperationFuture<Boolean> 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();
}
});
}
Expand All @@ -113,11 +115,10 @@ public void save(final Object objectToSave) {
final CouchbaseDocument converted = new CouchbaseDocument();
couchbaseConverter.write(objectToSave, converted);

execute(new BucketCallback<OperationFuture<Boolean>>() {
execute(new BucketCallback<Boolean>() {
@Override
public OperationFuture<Boolean> 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();
}
});
}
Expand All @@ -135,11 +136,10 @@ public void update(final Object objectToSave) {
final CouchbaseDocument converted = new CouchbaseDocument();
couchbaseConverter.write(objectToSave, converted);

execute(new BucketCallback<OperationFuture<Boolean>>() {
execute(new BucketCallback<Boolean>() {
@Override
public OperationFuture<Boolean> 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();
}
});

Expand Down Expand Up @@ -208,10 +208,10 @@ public void remove(final Object objectToRemove) {
ensureNotIterable(objectToRemove);

if (objectToRemove instanceof String) {
execute(new BucketCallback<OperationFuture<Boolean>>() {
execute(new BucketCallback<Boolean>() {
@Override
public OperationFuture<Boolean> doInBucket() {
return client.delete((String) objectToRemove);
public Boolean doInBucket() throws InterruptedException, ExecutionException {
return client.delete((String) objectToRemove).get();
}
});
return;
Expand All @@ -235,11 +235,18 @@ public void remove(final Collection<? extends Object> batchToRemove) {
}
}

@Override
public <T> T execute(final BucketCallback<T> 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);
}
}

Expand Down
@@ -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);
}

}
@@ -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);
}

}

0 comments on commit dd9c3ed

Please sign in to comment.