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 57e11b62..fd03b81e 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java @@ -32,7 +32,7 @@ import java.util.concurrent.CancellationException; /** * Simple {@link PersistenceExceptionTranslator} for Couchbase. - * + *

* 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. @@ -45,20 +45,21 @@ public class CouchbaseExceptionTranslator implements PersistenceExceptionTransla * Translate Couchbase specific exceptions to spring exceptions if possible. * * @param ex the exception to translate. + * * @return the translated exception or null. */ - @Override - public final DataAccessException translateExceptionIfPossible(final RuntimeException ex) { + @Override + public final DataAccessException translateExceptionIfPossible(final RuntimeException ex) { - if (ex instanceof ConnectionException) { - return new DataAccessResourceFailureException(ex.getMessage(), ex); - } - - if (ex instanceof ObservedException - || ex instanceof ObservedTimeoutException - || ex instanceof ObservedModifiedException) { - return new DataIntegrityViolationException(ex.getMessage(), ex); - } + if (ex instanceof ConnectionException) { + return new DataAccessResourceFailureException(ex.getMessage(), ex); + } + + if (ex instanceof ObservedException + || ex instanceof ObservedTimeoutException + || ex instanceof ObservedModifiedException) { + return new DataIntegrityViolationException(ex.getMessage(), ex); + } if (ex instanceof CancellationException) { throw new OperationCancellationException(ex.getMessage(), ex); @@ -67,8 +68,9 @@ public class CouchbaseExceptionTranslator implements PersistenceExceptionTransla if (ex instanceof InvalidViewException) { throw new InvalidDataAccessResourceUsageException(ex.getMessage(), ex); } - - return null; - } + + // Unable to translate exception, therefore just throw the original! + throw ex; + } } diff --git a/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java b/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java index ff812dcb..694a35ba 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseOperations.java @@ -33,79 +33,80 @@ public interface CouchbaseOperations { /** * Save the given object. - * + *

*

When the document already exists (specified by its unique id), then it will be overriden. Otherwise it will be * created.

* * @param objectToSave the object to store in the bucket. */ void save(Object objectToSave); - + /** * Save a list of objects. - * + *

*

When one of the documents already exists (specified by its unique id), then it will be overriden. Otherwise it * will be created.

* * @param batchToSave the list of objects to store in the bucket. */ - void save(Collection batchToSave); - + void save(Collection batchToSave); + /** * Insert the given object. - * + *

*

When the document already exists (specified by its unique id), then it will not be overriden. Use the * {@link CouchbaseOperations#save} method for this task.

* * @param objectToSave the object to add to the bucket. */ void insert(Object objectToSave); - + /** * Insert a list of objects. - * + *

*

When one of the documents already exists (specified by its unique id), then it will not be overriden. Use the * {@link CouchbaseOperations#save} method for this.

* * @param batchToSave the list of objects to add to the bucket. */ - void insert(Collection batchToSave); + void insert(Collection batchToSave); /** * Update the given object. - * + *

*

When the document does not exist (specified by its unique id) it will not be created. Use the * {@link CouchbaseOperations#save} method for this.

* * @param objectToSave the object to add to the bucket. */ void update(Object objectToSave); - + /** * Insert a list of objects. - * + *

*

If one of the documents does not exist (specified by its unique id), then it will not be created. Use the * {@link CouchbaseOperations#save} method for this.

* * @param batchToSave the list of objects to add to the bucket. */ - void update(Collection batchToSave); - + void update(Collection batchToSave); + /** * Find an object by its given Id and map it to the corresponding entity. * * @param id the unique ID of the document. * @param entityClass the entity to map to. + * * @return returns the found object or null otherwise. */ T findById(String id, Class entityClass); /** * Query a View for a list of documents of type T. - * + *

*

There is no need to {@link Query#setIncludeDocs(boolean)} explicitely, because it will be set to true all the * time. It is valid to pass in a empty constructed {@link Query} object.

- * + *

*

This method does not work with reduced views, because they by design do not contain references to original * objects. Use the provided {@link #queryView} method for more flexibility and direct access.

* @@ -113,6 +114,7 @@ public interface CouchbaseOperations { * @param view the name of the viewName. * @param query the Query object to customize the viewName query. * @param entityClass the entity to map to. + * * @return the converted collection */ List findByView(String design, String view, Query query, Class entityClass); @@ -120,17 +122,16 @@ public interface CouchbaseOperations { /** * Query a View with direct access to the {@link ViewResponse}. - * *

This method is available to ease the working with views by still wrapping exceptions into the Spring * infrastructure.

- * *

It is especially needed if you want to run reduced viewName queries, because they can't be mapped onto entities * directly.

* * @param design the name of the designDocument document. * @param view the name of the viewName. * @param query the Query object to customize the viewName query. - * @return + * + * @return ViewResponse containing the results of the query. */ ViewResponse queryView(String design, String view, Query query); @@ -138,13 +139,14 @@ public interface CouchbaseOperations { * Checks if the given document exists. * * @param id the unique ID of the document. + * * @return whether the document could be found or not. */ boolean exists(String id); /** * Remove the given object from the bucket by id. - * + *

* If the object is a String, it will be treated as the document key * directly. * @@ -157,22 +159,24 @@ public interface CouchbaseOperations { * * @param batchToRemove the list of Objects to remove. */ - void remove(Collection batchToRemove); + void remove(Collection batchToRemove); /** * Executes a BucketCallback translating any exceptions as necessary. - * + *

* Allows for returning a result object, that is a domain object or a collection of domain objects. * * @param action the action to execute in the callback. * @param the return type. - * @return + * + * @return the return type. */ T execute(BucketCallback action); /** * Returns the underlying {@link CouchbaseConverter}. - * @return + * + * @return CouchbaseConverter. */ CouchbaseConverter getConverter(); 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 02ea0ecf..60251763 100644 --- a/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java +++ b/src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java @@ -26,11 +26,20 @@ 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; -import org.springframework.data.couchbase.core.convert.translation.TranslationService; -import org.springframework.data.couchbase.core.mapping.*; +import org.springframework.data.couchbase.core.mapping.CouchbaseDocument; +import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; +import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; +import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; +import org.springframework.data.couchbase.core.mapping.CouchbaseStorable; import org.springframework.data.mapping.context.MappingContext; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -41,36 +50,32 @@ public class CouchbaseTemplate implements CouchbaseOperations { private CouchbaseClient client; private CouchbaseConverter couchbaseConverter; - protected final MappingContext, - CouchbasePersistentProperty> mappingContext; + protected final MappingContext, CouchbasePersistentProperty> mappingContext; private static final Collection ITERABLE_CLASSES; - private final CouchbaseExceptionTranslator exceptionTranslator = - new CouchbaseExceptionTranslator(); - private final TranslationService translationService; - - static { - Set iterableClasses = new HashSet(); - iterableClasses.add(List.class.getName()); - iterableClasses.add(Collection.class.getName()); - iterableClasses.add(Iterator.class.getName()); - ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses); - } + private final CouchbaseExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator(); + private final JacksonTranslationService translationService; + + static { + final Set iterableClasses = new HashSet(); + iterableClasses.add(List.class.getName()); + iterableClasses.add(Collection.class.getName()); + iterableClasses.add(Iterator.class.getName()); + ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses); + } public CouchbaseTemplate(final CouchbaseClient client) { this(client, null); } - public CouchbaseTemplate(final CouchbaseClient client, - final CouchbaseConverter converter) { + public CouchbaseTemplate(final CouchbaseClient client, final CouchbaseConverter converter) { this.client = client; - couchbaseConverter = converter == null ? getDefaultConverter(client) : converter; + couchbaseConverter = converter == null ? getDefaultConverter() : converter; mappingContext = couchbaseConverter.getMappingContext(); translationService = new JacksonTranslationService(); } - private CouchbaseConverter getDefaultConverter(final CouchbaseClient client) { - MappingCouchbaseConverter converter = new MappingCouchbaseConverter( - new CouchbaseMappingContext()); + private CouchbaseConverter getDefaultConverter() { + final MappingCouchbaseConverter converter = new MappingCouchbaseConverter(new CouchbaseMappingContext()); converter.afterPropertiesSet(); return converter; } @@ -84,7 +89,7 @@ public class CouchbaseTemplate implements CouchbaseOperations { } public final void insert(final Object objectToSave) { - ensureNotIterable(objectToSave); + ensureNotIterable(objectToSave); final CouchbaseDocument converted = new CouchbaseDocument(); couchbaseConverter.write(objectToSave, converted); @@ -96,16 +101,15 @@ public class CouchbaseTemplate implements CouchbaseOperations { } }); } - - public final void insert(final Collection batchToSave) { - Iterator iter = batchToSave.iterator(); - while (iter.hasNext()) { - insert(iter.next()); - } + + public final void insert(final Collection batchToSave) { + for (final Object aBatchToSave : batchToSave) { + insert(aBatchToSave); + } } public void save(final Object objectToSave) { - ensureNotIterable(objectToSave); + ensureNotIterable(objectToSave); final CouchbaseDocument converted = new CouchbaseDocument(); couchbaseConverter.write(objectToSave, converted); @@ -117,16 +121,15 @@ public class CouchbaseTemplate implements CouchbaseOperations { } }); } - - public void save(final Collection batchToSave) { - Iterator iter = batchToSave.iterator(); - while (iter.hasNext()) { - save(iter.next()); + + public void save(final Collection batchToSave) { + for (final Object aBatchToSave : batchToSave) { + save(aBatchToSave); } } public void update(final Object objectToSave) { - ensureNotIterable(objectToSave); + ensureNotIterable(objectToSave); final CouchbaseDocument converted = new CouchbaseDocument(); couchbaseConverter.write(objectToSave, converted); @@ -139,14 +142,13 @@ public class CouchbaseTemplate implements CouchbaseOperations { }); } - - public void update(final Collection batchToSave) { - Iterator iter = batchToSave.iterator(); - while (iter.hasNext()) { - save(iter.next()); - } + + public void update(final Collection batchToSave) { + for (final Object aBatchToSave : batchToSave) { + save(aBatchToSave); + } } - + public final T findById(final String id, final Class entityClass) { String result = execute(new BucketCallback() { @Override @@ -155,18 +157,17 @@ public class CouchbaseTemplate implements CouchbaseOperations { } }); - if (result == null) { - return null; - } + if (result == null) { + return null; + } - CouchbaseDocument converted = new CouchbaseDocument(id); - return couchbaseConverter.read(entityClass, (CouchbaseDocument) translateDecode(result, converted)); + final CouchbaseDocument converted = new CouchbaseDocument(id); + return couchbaseConverter.read(entityClass, (CouchbaseDocument) translateDecode(result, converted)); } @Override - public List findByView(final String designName, final String viewName, - final Query query, final Class entityClass) { + public List findByView(final String designName, final String viewName, final Query query, final Class entityClass) { if (!query.willIncludeDocs()) { query.setIncludeDocs(true); @@ -175,25 +176,23 @@ public class CouchbaseTemplate implements CouchbaseOperations { query.setReduce(false); } - ViewResponse response = queryView(designName, viewName, query); + final ViewResponse response = queryView(designName, viewName, query); - List result = new ArrayList(response.size()); - for (ViewRow row : response) { - CouchbaseDocument converted = new CouchbaseDocument(row.getId()); - result.add(couchbaseConverter.read(entityClass, - (CouchbaseDocument) translateDecode((String) row.getDocument(), converted))); + final List result = new ArrayList(response.size()); + for (final ViewRow row : response) { + final CouchbaseDocument converted = new CouchbaseDocument(row.getId()); + result.add(couchbaseConverter.read(entityClass, (CouchbaseDocument) translateDecode((String) row.getDocument(), converted))); } return result; } @Override - public ViewResponse queryView(final String designName, final String viewName, - final Query query) { + public ViewResponse queryView(final String designName, final String viewName, final Query query) { return execute(new BucketCallback() { @Override public ViewResponse doInBucket() { - View view = client.getView(designName, viewName); + final View view = client.getView(designName, viewName); return client.query(view, query); } }); @@ -223,10 +222,9 @@ public class CouchbaseTemplate implements CouchbaseOperations { }); } - public void remove(final Collection batchToRemove) { - Iterator iter = batchToRemove.iterator(); - while (iter.hasNext()) { - remove(iter.next()); + public void remove(final Collection batchToRemove) { + for (final Object aBatchToRemove : batchToRemove) { + remove(aBatchToRemove); } } @@ -235,7 +233,7 @@ public class CouchbaseTemplate implements CouchbaseOperations { try { return action.doInBucket(); } catch (RuntimeException e) { - throw potentiallyConvertRuntimeException(e); + throw exceptionTranslator.translateExceptionIfPossible(e); } catch (TimeoutException e) { throw new QueryTimeoutException(e.getMessage(), e); } catch (InterruptedException e) { @@ -247,13 +245,13 @@ public class CouchbaseTemplate implements CouchbaseOperations { @Override public boolean exists(final String id) { - String result = execute(new BucketCallback() { + final String result = execute(new BucketCallback() { @Override public String doInBucket() { return (String) client.get(id); } }); - return result == null ? false : true; + return result != null; } /** @@ -261,18 +259,13 @@ public class CouchbaseTemplate implements CouchbaseOperations { * * @param o the object to verify. */ - protected final void ensureNotIterable(Object o) { - if (null != o) { - if (o.getClass().isArray() || ITERABLE_CLASSES.contains(o.getClass().getName())) { - throw new IllegalArgumentException("Cannot use a collection here."); - } - } - } - - private RuntimeException potentiallyConvertRuntimeException(final RuntimeException ex) { - RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex); - return resolved == null ? ex : resolved; - } + protected final void ensureNotIterable(Object o) { + if (null != o) { + if (o.getClass().isArray() || ITERABLE_CLASSES.contains(o.getClass().getName())) { + throw new IllegalArgumentException("Cannot use a collection here."); + } + } + } @Override public CouchbaseConverter getConverter() {