DATADOC-4 - Improved MongoTemplate exception handling
- moved exception translation from MongoDbUtils to MongoExceptionTranslator - don't let MongoFactoryBean implement PersistenceExceptionTranslator - heavily refactored MongoTemplate to let higher level methods use callbacks to centralize exception handling in the callback executing methods - changed return type of MongoOperations.getCollectionNames to Set<String> as returning a List implies same order, that we can't guarantee actually - polished JavaDoc of MongoOperations - added assertions to methods - changed methods taking a List<Object> to take a List<? extends Object> instead - added abstract unit test for MongoOperations to define tests regarding expected exception behavior - let MongoTemplateUnitTests extend MongoOperationsUnitTests
This commit is contained in:
@@ -18,18 +18,11 @@ package org.springframework.data.document.mongodb;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.data.document.UncategorizedDocumentStoreException;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
|
||||
/**
|
||||
* Helper class featuring helper methods for internal MongoDb classes.
|
||||
@@ -53,36 +46,6 @@ abstract class MongoDbUtils {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given runtime exception to an appropriate exception from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
* Return null if no translation is appropriate: any other exception may
|
||||
* have resulted from user code, and should not be translated.
|
||||
* @param ex runtime exception that occurred
|
||||
* @return the corresponding DataAccessException instance,
|
||||
* or <code>null</code> if the exception should not be translated
|
||||
*/
|
||||
public static DataAccessException translateMongoExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
// Check for well-known MongoException subclasses.
|
||||
|
||||
// All other MongoExceptions
|
||||
if(ex instanceof DuplicateKey) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(),ex);
|
||||
}
|
||||
if(ex instanceof Network) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof MongoException) {
|
||||
return new UncategorizedDocumentStoreException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
|
||||
*
|
||||
|
||||
@@ -16,24 +16,51 @@
|
||||
package org.springframework.data.document.mongodb;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.document.UncategorizedDocumentStoreException;
|
||||
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.MongoException.DuplicateKey;
|
||||
import com.mongodb.MongoException.Network;
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} for Mongo.
|
||||
* Simple {@link PersistenceExceptionTranslator} for Mongo. 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.
|
||||
* @param ex runtime exception that occurred
|
||||
* @return the corresponding DataAccessException instance, or {@literal null} if the exception should not be translated
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
|
||||
* translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#
|
||||
* translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
return MongoDbUtils.translateMongoExceptionIfPossible(ex);
|
||||
}
|
||||
// Check for well-known MongoException subclasses.
|
||||
|
||||
// All other MongoExceptions
|
||||
if (ex instanceof DuplicateKey) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof Network) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof MongoException) {
|
||||
return new UncategorizedDocumentStoreException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.Mongo;
|
||||
@@ -38,8 +36,7 @@ import com.mongodb.ServerAddress;
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean,
|
||||
PersistenceExceptionTranslator {
|
||||
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean {
|
||||
|
||||
|
||||
/**
|
||||
@@ -120,10 +117,4 @@ public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
logger.debug("Translating " + ex);
|
||||
return MongoDbUtils.translateMongoExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.document.mongodb;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -27,7 +28,7 @@ import com.mongodb.DBObject;
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Mark Pollack
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface MongoOperations {
|
||||
|
||||
@@ -38,7 +39,7 @@ public interface MongoOperations {
|
||||
String getDefaultCollectionName();
|
||||
|
||||
/**
|
||||
* The default collection used by this template
|
||||
* The default collection used by this template.
|
||||
* @return The default collection used by this template
|
||||
*/
|
||||
DBCollection getDefaultCollection();
|
||||
@@ -117,17 +118,17 @@ public interface MongoOperations {
|
||||
DBCollection createCollection(String collectionName);
|
||||
|
||||
/**
|
||||
* Create a collect with the provided name and options
|
||||
* Create a collect with the provided name and options.
|
||||
* @param collectionName name of the collection
|
||||
* @param collectionOptions options to use when creating the collection.
|
||||
*/
|
||||
void createCollection(String collectionName, CollectionOptions collectionOptions);
|
||||
|
||||
/**
|
||||
* A list of collection names
|
||||
* A set of collection names.
|
||||
* @return list of collection names
|
||||
*/
|
||||
List<String> getCollectionNames();
|
||||
Set<String> getCollectionNames();
|
||||
|
||||
/**
|
||||
* Get a collection by name, creating it if it doesn't exist.
|
||||
@@ -216,14 +217,14 @@ public interface MongoOperations {
|
||||
*
|
||||
* @param listToSave the list of objects to save.
|
||||
*/
|
||||
void insertList(List<Object> listToSave);
|
||||
void insertList(List<? extends Object> listToSave);
|
||||
|
||||
/**
|
||||
* Insert a list of objects into the specified collection in a single batch write to the database.
|
||||
* @param collectionName name of the collection to store the object in
|
||||
* @param listToSave the list of objects to save.
|
||||
*/
|
||||
void insertList(String collectionName, List<Object> listToSave);
|
||||
void insertList(String collectionName, List<? extends Object> listToSave);
|
||||
|
||||
/**
|
||||
* Insert a list of objects into the specified collection using the provided MongoWriter instance
|
||||
@@ -233,7 +234,7 @@ public interface MongoOperations {
|
||||
* @param listToSave the list of objects to save.
|
||||
* @param writer the writer to convert the object to save into a DBObject
|
||||
*/
|
||||
<T> void insertList(String collectionName, List<T> listToSave, MongoWriter<T> writer);
|
||||
<T> void insertList(String collectionName, List<? extends T> listToSave, MongoWriter<T> writer);
|
||||
|
||||
/**
|
||||
* Save the object to the default collection. This will perform an insert if the object is not already
|
||||
|
||||
@@ -16,19 +16,20 @@
|
||||
|
||||
package org.springframework.data.document.mongodb;
|
||||
|
||||
import static java.lang.String.*;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.jca.cci.core.ConnectionCallback;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
@@ -39,7 +40,6 @@ import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.Mongo;
|
||||
import com.mongodb.MongoException;
|
||||
import com.mongodb.WriteResult;
|
||||
import com.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
@@ -53,10 +53,10 @@ import com.mongodb.util.JSON;
|
||||
public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
|
||||
private static final String ID = "_id";
|
||||
private static final String COLLECTION_ERROR_TEMPLATE = "Error creating collection %s: %s";
|
||||
|
||||
private final MongoConverter mongoConverter;
|
||||
private final Mongo mongo;
|
||||
private final MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
|
||||
|
||||
private String defaultCollectionName;
|
||||
private String databaseName;
|
||||
@@ -98,7 +98,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password to use to authenticate with the Mongo database
|
||||
* Sets the password to use to authenticate with the Mongo database.
|
||||
*
|
||||
* @param password The password to use
|
||||
*/
|
||||
@@ -107,10 +107,20 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the default collection to be used.
|
||||
*
|
||||
* @param defaultCollectionName
|
||||
*/
|
||||
public void setDefaultCollectionName(String defaultCollectionName) {
|
||||
this.defaultCollectionName = defaultCollectionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database name to be used.
|
||||
*
|
||||
* @param databaseName
|
||||
*/
|
||||
public void setDatabaseName(String databaseName) {
|
||||
Assert.notNull(databaseName);
|
||||
this.databaseName = databaseName;
|
||||
@@ -127,7 +137,12 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#getDefaultCollection()
|
||||
*/
|
||||
public DBCollection getDefaultCollection() {
|
||||
return getDb().getCollection(getDefaultCollectionName());
|
||||
|
||||
return execute(new DBCallback<DBCollection>() {
|
||||
public DBCollection doInDB(DB db) throws MongoException, DataAccessException {
|
||||
return db.getCollection(getDefaultCollectionName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -140,33 +155,41 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#executeCommand(com.mongodb.DBObject)
|
||||
*/
|
||||
public void executeCommand(DBObject command) {
|
||||
CommandResult cr = getDb().command(command);
|
||||
String err = cr.getErrorMessage();
|
||||
if (err != null) {
|
||||
public void executeCommand(final DBObject command) {
|
||||
|
||||
CommandResult result = execute(new DBCallback<CommandResult>() {
|
||||
public CommandResult doInDB(DB db) throws MongoException, DataAccessException {
|
||||
return db.command(command);
|
||||
}
|
||||
});
|
||||
|
||||
String error = result.getErrorMessage();
|
||||
if (error != null) {
|
||||
throw new InvalidDataAccessApiUsageException("Command execution of " +
|
||||
command.toString() + " failed: " + err);
|
||||
command.toString() + " failed: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#execute(org.springframework.data.document.mongodb.DBCallback)
|
||||
*/
|
||||
public <T> T execute(DBCallback<T> action) {
|
||||
DB db = getDb();
|
||||
public <T> T execute(DbCallback<T> action) {
|
||||
|
||||
Assert.notNull(action);
|
||||
|
||||
try {
|
||||
DB db = getDb();
|
||||
return action.doInDB(db);
|
||||
} catch (MongoException e) {
|
||||
throw MongoDbUtils.translateMongoExceptionIfPossible(e);
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#execute(org.springframework.data.document.mongodb.CollectionCallback)
|
||||
*/
|
||||
public <T> T execute(CollectionCallback<T> action) {
|
||||
return execute(action, defaultCollectionName);
|
||||
public <T> T execute(CollectionCallback<T> callback) {
|
||||
return execute(callback, defaultCollectionName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -174,79 +197,126 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
*/
|
||||
public <T> T execute(CollectionCallback<T> callback, String collectionName) {
|
||||
|
||||
Assert.notNull(callback);
|
||||
|
||||
try {
|
||||
return callback.doInCollection(getCollection(collectionName));
|
||||
DBCollection collection = getDb().getCollection(collectionName);
|
||||
return callback.doInCollection(collection);
|
||||
} catch (MongoException e) {
|
||||
throw MongoDbUtils.translateMongoExceptionIfPossible(e);
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Central callback executing method to do queries against the datastore that requires reading a collection of
|
||||
* objects. It will take the following steps <ol> <li>Execute the given {@link ConnectionCallback} for a
|
||||
* {@link DBCursor}.</li> <li>Prepare that {@link DBCursor} with the given {@link CursorPreparer} (will be skipped
|
||||
* if {@link CursorPreparer} is {@literal null}</li> <li>Iterate over the {@link DBCursor} and applies the given
|
||||
* {@link DbObjectCallback} to each of the {@link DBObject}s collecting the actual result {@link List}.</li> <ol>
|
||||
*
|
||||
* @param <T>
|
||||
* @param collectionCallback the callback to retrieve the {@link DBCursor} with
|
||||
* @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
|
||||
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
|
||||
* @param collectionName the collection to be queried
|
||||
* @return
|
||||
*/
|
||||
private <T> List<T> executeEach(CollectionCallback<DBCursor> collectionCallback, CursorPreparer preparer,
|
||||
DbObjectCallback<T> objectCallback, String collectionName) {
|
||||
|
||||
try {
|
||||
DBCursor cursor = collectionCallback.doInCollection(getCollection(collectionName));
|
||||
|
||||
if (preparer != null) {
|
||||
preparer.prepare(cursor);
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
|
||||
for (DBObject object : cursor) {
|
||||
result.add(objectCallback.doWith(object));
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (MongoException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#executeInSession(org.springframework.data.document.mongodb.DBCallback)
|
||||
*/
|
||||
public <T> T executeInSession(DBCallback<T> action) {
|
||||
DB db = getDb();
|
||||
db.requestStart();
|
||||
try {
|
||||
return action.doInDB(db);
|
||||
} catch (MongoException e) {
|
||||
throw MongoDbUtils.translateMongoExceptionIfPossible(e);
|
||||
} finally {
|
||||
db.requestDone();
|
||||
}
|
||||
public <T> T executeInSession(final DBCallback<T> action) {
|
||||
|
||||
return execute(new DBCallback<T>() {
|
||||
public T doInDB(DB db) throws MongoException, DataAccessException {
|
||||
try {
|
||||
db.requestStart();
|
||||
return action.doInDB(db);
|
||||
} finally {
|
||||
db.requestDone();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#createCollection(java.lang.String)
|
||||
*/
|
||||
public DBCollection createCollection(String collectionName) {
|
||||
try {
|
||||
return getDb().createCollection(collectionName, new BasicDBObject());
|
||||
} catch (MongoException e) {
|
||||
throw new InvalidDataAccessApiUsageException(format(COLLECTION_ERROR_TEMPLATE, collectionName, e.getMessage()), e);
|
||||
}
|
||||
public DBCollection createCollection(final String collectionName) {
|
||||
return execute(new DBCallback<DBCollection>() {
|
||||
public DBCollection doInDB(DB db) throws MongoException, DataAccessException {
|
||||
return db.createCollection(collectionName, new BasicDBObject());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#createCollection(java.lang.String, org.springframework.data.document.mongodb.CollectionOptions)
|
||||
*/
|
||||
public void createCollection(String collectionName, CollectionOptions collectionOptions) {
|
||||
try {
|
||||
getDb().createCollection(collectionName, convertToDbObject(collectionOptions));
|
||||
} catch (MongoException e) {
|
||||
throw new InvalidDataAccessApiUsageException(format(COLLECTION_ERROR_TEMPLATE, collectionName, e.getMessage()), e);
|
||||
}
|
||||
public void createCollection(final String collectionName, final CollectionOptions collectionOptions) {
|
||||
execute(new DBCallback<Void>() {
|
||||
public Void doInDB(DB db) throws MongoException, DataAccessException {
|
||||
db.createCollection(collectionName, convertToDbObject(collectionOptions));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#getCollection(java.lang.String)
|
||||
*/
|
||||
public DBCollection getCollection(String collectionName) {
|
||||
try {
|
||||
return getDb().getCollection(collectionName);
|
||||
} catch (MongoException e) {
|
||||
throw new InvalidDataAccessApiUsageException(format(COLLECTION_ERROR_TEMPLATE, collectionName, e.getMessage()), e);
|
||||
}
|
||||
public DBCollection getCollection(final String collectionName) {
|
||||
return execute(new DBCallback<DBCollection>() {
|
||||
public DBCollection doInDB(DB db) throws MongoException, DataAccessException {
|
||||
return db.getCollection(collectionName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#collectionExists(java.lang.String)
|
||||
*/
|
||||
public boolean collectionExists(String collectionName) {
|
||||
try {
|
||||
return getDb().collectionExists(collectionName);
|
||||
} catch (MongoException e) {
|
||||
throw new InvalidDataAccessApiUsageException("Error creating collection " + collectionName + ": " + e.getMessage(), e);
|
||||
}
|
||||
public boolean collectionExists(final String collectionName) {
|
||||
return execute(new DBCallback<Boolean>() {
|
||||
public Boolean doInDB(DB db) throws MongoException, DataAccessException {
|
||||
return db.collectionExists(collectionName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#dropCollection(java.lang.String)
|
||||
*/
|
||||
public void dropCollection(String collectionName) {
|
||||
getDb().getCollection(collectionName)
|
||||
.drop();
|
||||
|
||||
execute(new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.drop();
|
||||
return null;
|
||||
}
|
||||
}, collectionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -287,21 +357,24 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#insertList(java.util.List)
|
||||
*/
|
||||
public void insertList(List<Object> listToSave) {
|
||||
public void insertList(List<? extends Object> listToSave) {
|
||||
insertList(getRequiredDefaultCollectionName(), listToSave);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#insertList(java.lang.String, java.util.List)
|
||||
*/
|
||||
public void insertList(String collectionName, List<Object> listToSave) {
|
||||
public void insertList(String collectionName, List<? extends Object> listToSave) {
|
||||
insertList(collectionName, listToSave, this.mongoConverter);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#insertList(java.lang.String, java.util.List, org.springframework.data.document.mongodb.MongoWriter)
|
||||
*/
|
||||
public <T> void insertList(String collectionName, List<T> listToSave, MongoWriter<T> writer) {
|
||||
public <T> void insertList(String collectionName, List<? extends T> listToSave, MongoWriter<T> writer) {
|
||||
|
||||
Assert.notNull(writer);
|
||||
|
||||
List<DBObject> dbObjectList = new ArrayList<DBObject>();
|
||||
for (T o : listToSave) {
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
@@ -341,51 +414,56 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
}
|
||||
|
||||
|
||||
protected Object insertDBObject(String collectionName, DBObject dbDoc) {
|
||||
if (dbDoc.keySet().size() > 0 ) {
|
||||
WriteResult wr = null;
|
||||
try {
|
||||
wr = getDb().getCollection(collectionName).insert(dbDoc);
|
||||
return dbDoc.get(ID);
|
||||
} catch (MongoException e) {
|
||||
throw new DataRetrievalFailureException(wr.getLastError().getErrorMessage(), e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
protected Object insertDBObject(String collectionName, final DBObject dbDoc) {
|
||||
|
||||
if (dbDoc.keySet().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return execute(new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.insert(dbDoc);
|
||||
return dbDoc.get(ID);
|
||||
}
|
||||
}, collectionName);
|
||||
}
|
||||
|
||||
protected List<Object> insertDBObjectList(String collectionName, List<DBObject> dbDocList) {
|
||||
if (!dbDocList.isEmpty()) {
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
WriteResult wr = null;
|
||||
try {
|
||||
wr = getDb().getCollection(collectionName).insert(dbDocList);
|
||||
for (DBObject dbo : dbDocList) {
|
||||
ids.add(dbo.get(ID));
|
||||
}
|
||||
return ids;
|
||||
} catch (MongoException e) {
|
||||
throw new DataRetrievalFailureException(wr.getLastError().getErrorMessage(), e);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
|
||||
|
||||
|
||||
protected List<Object> insertDBObjectList(String collectionName, final List<DBObject> dbDocList) {
|
||||
|
||||
if (dbDocList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
execute(new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.insert(dbDocList);
|
||||
return null;
|
||||
}
|
||||
}, collectionName);
|
||||
|
||||
List<Object> ids = new ArrayList<Object>();
|
||||
for (DBObject dbo : dbDocList) {
|
||||
ids.add(dbo.get(ID));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
protected Object saveDBObject(String collectionName, DBObject dbDoc) {
|
||||
if (dbDoc.keySet().size() > 0 ) {
|
||||
WriteResult wr = null;
|
||||
try {
|
||||
wr = getDb().getCollection(collectionName).save(dbDoc);
|
||||
return dbDoc.get(ID);
|
||||
} catch (MongoException e) {
|
||||
throw new DataRetrievalFailureException(wr.getLastError().getErrorMessage(), e);
|
||||
}
|
||||
} else {
|
||||
protected Object saveDBObject(String collectionName, final DBObject dbDoc) {
|
||||
|
||||
if (dbDoc.keySet().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return execute(new CollectionCallback<Object>() {
|
||||
|
||||
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.save(dbDoc);
|
||||
return dbDoc.get(ID);
|
||||
}
|
||||
}, collectionName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -398,13 +476,13 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#updateFirst(java.lang.String, com.mongodb.DBObject, com.mongodb.DBObject)
|
||||
*/
|
||||
public void updateFirst(String collectionName, DBObject queryDoc, DBObject updateDoc) {
|
||||
|
||||
try {
|
||||
getDb().getCollection(collectionName).update(queryDoc, updateDoc);
|
||||
} catch (MongoException e) {
|
||||
throw new DataRetrievalFailureException("Error during update using " + queryDoc + ", " + updateDoc + "!", e);
|
||||
}
|
||||
public void updateFirst(String collectionName, final DBObject queryDoc, final DBObject updateDoc) {
|
||||
execute(new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.update(queryDoc, updateDoc);
|
||||
return null;
|
||||
}
|
||||
}, collectionName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -417,12 +495,13 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#updateMulti(java.lang.String, com.mongodb.DBObject, com.mongodb.DBObject)
|
||||
*/
|
||||
public void updateMulti(String collectionName, DBObject queryDoc, DBObject updateDoc) {
|
||||
try {
|
||||
getDb().getCollection(collectionName).updateMulti(queryDoc, updateDoc);
|
||||
} catch (MongoException e) {
|
||||
throw new DataRetrievalFailureException("Error during updateMulti using " + queryDoc + ", " + updateDoc + "!", e);
|
||||
}
|
||||
public void updateMulti(String collectionName, final DBObject queryDoc, final DBObject updateDoc) {
|
||||
execute(new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.updateMulti(queryDoc, updateDoc);
|
||||
return null;
|
||||
}
|
||||
}, collectionName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -435,12 +514,13 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#remove(java.lang.String, com.mongodb.DBObject)
|
||||
*/
|
||||
public void remove(String collectionName, DBObject queryDoc) {
|
||||
try {
|
||||
getDb().getCollection(collectionName).remove(queryDoc);
|
||||
} catch (MongoException e) {
|
||||
throw new DataRetrievalFailureException("Error during remove using " + queryDoc + "!", e);
|
||||
}
|
||||
public void remove(String collectionName, final DBObject queryDoc) {
|
||||
execute(new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
collection.remove(queryDoc);
|
||||
return null;
|
||||
}
|
||||
}, collectionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -448,53 +528,35 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#getCollection(java.lang.Class)
|
||||
*/
|
||||
public <T> List<T> getCollection(Class<T> targetClass) {
|
||||
|
||||
List<T> results = new ArrayList<T>();
|
||||
DBCollection collection = getDb().getCollection(getDefaultCollectionName());
|
||||
for (DBObject dbo : collection.find()) {
|
||||
Object obj = mongoConverter.read(targetClass, dbo);
|
||||
//effectively acts as a query on the collection restricting it to elements of a specific type
|
||||
if (targetClass.isInstance(obj)) {
|
||||
results.add(targetClass.cast(obj));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
return executeEach(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter, targetClass),
|
||||
getDefaultCollectionName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#getCollection(java.lang.String, java.lang.Class)
|
||||
*/
|
||||
public <T> List<T> getCollection(String collectionName, Class<T> targetClass) {
|
||||
|
||||
List<T> results = new ArrayList<T>();
|
||||
DBCollection collection = getDb().getCollection(collectionName);
|
||||
for (DBObject dbo : collection.find()) {
|
||||
Object obj = mongoConverter.read(targetClass, dbo);
|
||||
//effectively acts as a query on the collection restricting it to elements of a specific type
|
||||
if (targetClass.isInstance(obj)) {
|
||||
results.add(targetClass.cast(obj));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
return executeEach(new FindCallback(null), null, new ReadDbObjectCallback<T>(mongoConverter, targetClass),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#getCollectionNames()
|
||||
*/
|
||||
public List<String> getCollectionNames() {
|
||||
return new ArrayList<String>(getDb().getCollectionNames());
|
||||
public Set<String> getCollectionNames() {
|
||||
return execute(new DBCallback<Set<String>>() {
|
||||
public Set<String> doInDB(DB db) throws MongoException, DataAccessException {
|
||||
return db.getCollectionNames();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#getCollection(java.lang.String, java.lang.Class, org.springframework.data.document.mongodb.MongoReader)
|
||||
*/
|
||||
public <T> List<T> getCollection(String collectionName, Class<T> targetClass, MongoReader<T> reader) {
|
||||
List<T> results = new ArrayList<T>();
|
||||
DBCollection collection = getDb().getCollection(collectionName);
|
||||
for (DBObject dbo : collection.find()) {
|
||||
results.add(reader.read(targetClass, dbo));
|
||||
}
|
||||
return results;
|
||||
return executeEach(new FindCallback(null), null, new ReadDbObjectCallback<T>(reader, targetClass),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
// Queries that take JavaScript to express the query.
|
||||
@@ -562,37 +624,18 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#query(java.lang.String, com.mongodb.DBObject, java.lang.Class, org.springframework.data.document.mongodb.CursorPreparer)
|
||||
*/
|
||||
public <T> List<T> query(String collectionName, DBObject query, Class<T> targetClass, CursorPreparer preparer) {
|
||||
DBCollection collection = getDb().getCollection(collectionName);
|
||||
List<T> results = new ArrayList<T>();
|
||||
DBCursor cursor = collection.find(query);
|
||||
if (preparer != null) {
|
||||
preparer.prepare(cursor);
|
||||
}
|
||||
for (DBObject dbo : cursor) {
|
||||
Object obj = mongoConverter.read(targetClass,dbo);
|
||||
//effectively acts as a query on the collection restricting it to elements of a specific type
|
||||
if (targetClass.isInstance(obj)) {
|
||||
results.add(targetClass.cast(obj));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
return executeEach(new FindCallback(query), preparer, new ReadDbObjectCallback<T>(mongoConverter, targetClass),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperations#query(java.lang.String, com.mongodb.DBObject, java.lang.Class, org.springframework.data.document.mongodb.MongoReader)
|
||||
*/
|
||||
public <T> List<T> query(String collectionName, DBObject query, Class<T> targetClass, MongoReader<T> reader) {
|
||||
DBCollection collection = getDb().getCollection(collectionName);
|
||||
List<T> results = new ArrayList<T>();
|
||||
for (DBObject dbo : collection.find(query)) {
|
||||
results.add(reader.read(targetClass, dbo));
|
||||
}
|
||||
return results;
|
||||
return executeEach(new FindCallback(query), null, new ReadDbObjectCallback<T>(reader, targetClass),
|
||||
collectionName);
|
||||
}
|
||||
|
||||
public RuntimeException convertMongoAccessException(RuntimeException ex) {
|
||||
return MongoDbUtils.translateMongoExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
public DB getDb() {
|
||||
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
|
||||
@@ -635,16 +678,81 @@ public class MongoTemplate implements InitializingBean, MongoOperations {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
|
||||
* exception if the conversation failed. Thus allows safe rethrowing of the return value.
|
||||
*
|
||||
* @param ex
|
||||
* @return
|
||||
*/
|
||||
private RuntimeException potentiallyConvertRuntimeException(RuntimeException ex) {
|
||||
|
||||
RuntimeException resolved = this.exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() {
|
||||
if (this.getDefaultCollectionName() != null) {
|
||||
DB db = getDb();
|
||||
if (! db.collectionExists(getDefaultCollectionName())) {
|
||||
db.createCollection(getDefaultCollectionName(), null);
|
||||
if (!collectionExists(getDefaultCollectionName())) {
|
||||
createCollection(getDefaultCollectionName(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple {@link CollectionCallback} that takes a query {@link DBObject} and executes that against the
|
||||
* {@link DBCollection}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class FindCallback implements CollectionCallback<DBCursor> {
|
||||
|
||||
private final DBObject query;
|
||||
|
||||
public FindCallback(DBObject query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public DBCursor doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
return collection.find(query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple internal callback to allow operations on a {@link DBObject}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
|
||||
private interface DbObjectCallback<T> {
|
||||
|
||||
T doWith(DBObject object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple {@link DbObjectCallback} that will transform {@link DBObject} into the given target type using the given
|
||||
* {@link MongoReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
private static class ReadDbObjectCallback<T> implements DbObjectCallback<T> {
|
||||
|
||||
private final MongoReader<? super T> reader;
|
||||
private final Class<T> type;
|
||||
|
||||
public ReadDbObjectCallback(MongoReader<? super T> reader, Class<T> type) {
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T doWith(DBObject object) {
|
||||
return (T) reader.read(type, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright 2011 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.document.mongodb;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Abstract base class for unit tests to specify behaviour we expect from {@link MongoOperations}. Subclasses return
|
||||
* instances of their implementation and thus can see if it correctly implements the {@link MongoOperations} interface.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public abstract class MongoOperationsUnitTests {
|
||||
|
||||
@Mock
|
||||
CollectionCallback<Object> collectionCallback;
|
||||
@Mock
|
||||
DbCallback<Object> dbCallback;
|
||||
|
||||
MongoConverter converter;
|
||||
Person person;
|
||||
List<Person> persons;
|
||||
|
||||
@Before
|
||||
public final void operationsSetUp() {
|
||||
|
||||
person = new Person("Oliver");
|
||||
persons = Arrays.asList(person);
|
||||
|
||||
converter = new MongoConverter() {
|
||||
|
||||
public Object read(Class<? extends Object> clazz, DBObject dbo) {
|
||||
return person;
|
||||
}
|
||||
|
||||
public void write(Object t, DBObject dbo) {
|
||||
dbo.put("firstName", person.getFirstName());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void rejectsNullForCollectionCallback() {
|
||||
|
||||
getOperations().execute((CollectionCallback) null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void rejectsNullForCollectionCallback2() {
|
||||
getOperations().execute((CollectionCallback) null, "collection");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public void rejectsNullForDbCallback() {
|
||||
getOperations().execute((DbCallback) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForCollectionExists() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.collectionExists("foo");
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForCreateCollection() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.createCollection("foo");
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForCreateCollection2() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.createCollection("foo", new CollectionOptions(1, 1, true));
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForDropCollection() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.dropCollection("foo");
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForExecuteCollectionCallback() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.execute(collectionCallback);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForExecuteDbCallback() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.execute(dbCallback);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForExecuteCollectionCallbackAndCollection() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.execute(collectionCallback, "collection");
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForExecuteCommand() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.executeCommand(new BasicDBObject());
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForExecuteStringCommand() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.executeCommand("");
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForExecuteInSession() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.executeInSession(dbCallback);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetCollection() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.getCollection(Object.class);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetCollectionWithCollectionName() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.getCollection("collection");
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetCollectionWithCollectionNameAndType() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.getCollection("collection", Object.class);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetCollectionWithCollectionNameTypeAndReader() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.getCollection("collection", Object.class, converter);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetCollectionNames() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.getCollectionNames();
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetDefaultCollection() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.getDefaultCollection();
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForInsert() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.insert(person);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForInsert2() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.insert("collection", person);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForInsert3() {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.insert("collection", person, converter);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForInsertList() throws Exception {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.insertList(persons);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetInsertList2() throws Exception {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.insertList("collection", persons);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertsExceptionForGetInsertList3() throws Exception {
|
||||
new Execution() {
|
||||
@Override
|
||||
public void doWith(MongoOperations operations) {
|
||||
operations.insertList("collection", persons, converter);
|
||||
}
|
||||
}.assertDataAccessException();
|
||||
}
|
||||
|
||||
private abstract class Execution {
|
||||
|
||||
public void assertDataAccessException() {
|
||||
assertException(DataAccessException.class);
|
||||
}
|
||||
|
||||
public void assertException(Class<? extends Exception> exception) {
|
||||
|
||||
try {
|
||||
doWith(getOperationsForExceptionHandling());
|
||||
fail("Expected " + exception + " but completed without any!");
|
||||
} catch (Exception e) {
|
||||
assertTrue("Expected " + exception + " but got " + e, exception.isInstance(e));
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void doWith(MongoOperations operations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects an {@link MongoOperations} instance that will be used to check that invoking methods on it will only
|
||||
* cause {@link DataAccessException}s.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract MongoOperations getOperationsForExceptionHandling();
|
||||
|
||||
/**
|
||||
* Returns a plain {@link MongoOperations}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract MongoOperations getOperations();
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.mongodb.DB;
|
||||
@@ -36,7 +36,7 @@ import com.mongodb.MongoException;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MongoTemplateUnitTests {
|
||||
public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
|
||||
MongoTemplate template;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class MongoTemplateUnitTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.template = new MongoTemplate(mongo, "database");
|
||||
this.template = new MongoTemplate(mongo, "database", "default");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -61,7 +61,7 @@ public class MongoTemplateUnitTests {
|
||||
new MongoTemplate(null, "database");
|
||||
}
|
||||
|
||||
@Test(expected = DataRetrievalFailureException.class)
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void removeHandlesMongoExceptionProperly() throws Exception {
|
||||
MongoTemplate template = mockOutGetDb();
|
||||
when(db.getCollection("collection")).thenThrow(new MongoException("Exception!"));
|
||||
@@ -87,4 +87,22 @@ public class MongoTemplateUnitTests {
|
||||
stub(template.getDb()).toReturn(db);
|
||||
return template;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperationsUnitTests#getOperations()
|
||||
*/
|
||||
@Override
|
||||
protected MongoOperations getOperationsForExceptionHandling() {
|
||||
MongoTemplate template = spy(this.template);
|
||||
stub(template.getDb()).toThrow(new MongoException("Error!"));
|
||||
return template;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.document.mongodb.MongoOperationsUnitTests#getOperations()
|
||||
*/
|
||||
@Override
|
||||
protected MongoOperations getOperations() {
|
||||
return this.template;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,14 @@ public class Person {
|
||||
|
||||
private Person friend;
|
||||
|
||||
public Person() {
|
||||
|
||||
}
|
||||
|
||||
public Person(String firstname) {
|
||||
this.firstName = firstname;
|
||||
}
|
||||
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
|
||||
Reference in New Issue
Block a user