Compare commits
11 Commits
2.0.0.RC3
...
1.8.1.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f68effe155 | ||
|
|
6fc80f287e | ||
|
|
02aed56fd1 | ||
|
|
f1771504f6 | ||
|
|
741a27edae | ||
|
|
e1869abf3f | ||
|
|
c7be5bfcaa | ||
|
|
9968b752e7 | ||
|
|
e001c6bf89 | ||
|
|
913d383b99 | ||
|
|
f446d7e29f |
6
pom.xml
6
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RELEASE</version>
|
||||
<version>1.8.1.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data.build</groupId>
|
||||
<artifactId>spring-data-parent</artifactId>
|
||||
<version>1.7.0.RELEASE</version>
|
||||
<version>1.7.1.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
@@ -28,7 +28,7 @@
|
||||
<properties>
|
||||
<project.type>multi</project.type>
|
||||
<dist.id>spring-data-mongodb</dist.id>
|
||||
<springdata.commons>1.11.0.RELEASE</springdata.commons>
|
||||
<springdata.commons>1.11.1.RELEASE</springdata.commons>
|
||||
<mongo>2.13.0</mongo>
|
||||
<mongo.osgi>2.13.0</mongo.osgi>
|
||||
</properties>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RELEASE</version>
|
||||
<version>1.8.1.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.8.0.RELEASE</version>
|
||||
<version>1.8.1.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RELEASE</version>
|
||||
<version>1.8.1.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RELEASE</version>
|
||||
<version>1.8.1.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.8.0.RELEASE</version>
|
||||
<version>1.8.1.RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ package org.springframework.data.mongodb.config;
|
||||
import static org.springframework.data.config.ParsingUtils.*;
|
||||
import static org.springframework.data.mongodb.config.MongoParsingUtils.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
@@ -44,9 +48,21 @@ import com.mongodb.MongoURI;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Viktor Khoroshko
|
||||
*/
|
||||
public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final Set<String> MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES;
|
||||
|
||||
static {
|
||||
|
||||
Set<String> mongoUriAllowedAdditionalAttributes = new HashSet<String>();
|
||||
mongoUriAllowedAdditionalAttributes.add("id");
|
||||
mongoUriAllowedAdditionalAttributes.add("write-concern");
|
||||
|
||||
MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES = Collections.unmodifiableSet(mongoUriAllowedAdditionalAttributes);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element, org.springframework.beans.factory.support.AbstractBeanDefinition, org.springframework.beans.factory.xml.ParserContext)
|
||||
@@ -70,13 +86,10 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
BeanDefinitionBuilder dbFactoryBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleMongoDbFactory.class);
|
||||
setPropertyValue(dbFactoryBuilder, element, "write-concern", "writeConcern");
|
||||
|
||||
BeanDefinition mongoUri = getMongoUri(element);
|
||||
BeanDefinition mongoUri = getMongoUri(element, parserContext);
|
||||
|
||||
if (mongoUri != null) {
|
||||
if (element.getAttributes().getLength() >= 2 && !element.hasAttribute("write-concern")) {
|
||||
parserContext.getReaderContext().error("Configure either Mongo URI or details individually!",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
dbFactoryBuilder.addConstructorArgValue(mongoUri);
|
||||
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
|
||||
}
|
||||
@@ -149,12 +162,15 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Creates a {@link BeanDefinition} for a {@link MongoURI} or {@link MongoClientURI} depending on configured
|
||||
* attributes.
|
||||
* attributes. <br />
|
||||
* Errors when configured element contains {@literal uri} or {@literal client-uri} along with other attributes except
|
||||
* {@literal write-concern} and/or {@literal id}.
|
||||
*
|
||||
* @param element must not be {@literal null}.
|
||||
* @param parserContext
|
||||
* @return {@literal null} in case no client-/uri defined.
|
||||
*/
|
||||
private BeanDefinition getMongoUri(Element element) {
|
||||
private BeanDefinition getMongoUri(Element element, ParserContext parserContext) {
|
||||
|
||||
boolean hasClientUri = element.hasAttribute("client-uri");
|
||||
|
||||
@@ -162,6 +178,21 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
int allowedAttributesCount = 1;
|
||||
for (String attribute : MONGO_URI_ALLOWED_ADDITIONAL_ATTRIBUTES) {
|
||||
|
||||
if (element.hasAttribute(attribute)) {
|
||||
allowedAttributesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (element.getAttributes().getLength() > allowedAttributesCount) {
|
||||
|
||||
parserContext.getReaderContext().error(
|
||||
"Configure either " + (hasClientUri ? "Mongo Client URI" : "Mongo URI") + " or details individually!",
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
|
||||
Class<?> type = hasClientUri ? MongoClientURI.class : MongoURI.class;
|
||||
String uri = hasClientUri ? element.getAttribute("client-uri") : element.getAttribute("uri");
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
ReadDbObjectCallback<T> readCallback = new ReadDbObjectCallback<T>(mongoConverter, entityType, collection
|
||||
.getName());
|
||||
|
||||
return new CloseableIterableCusorAdapter<T>(cursorPreparer.prepare(cursor), exceptionTranslator, readCallback);
|
||||
return new CloseableIterableCursorAdapter<T>(cursorPreparer.prepare(cursor), exceptionTranslator, readCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -445,7 +445,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DB db = this.getDb();
|
||||
return action.doInDB(db);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
DBCollection collection = getAndPrepareCollection(getDb(), collectionName);
|
||||
return callback.doInCollection(collection);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1548,10 +1548,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
throw new InvalidDataAccessApiUsageException(String.format("Resource %s not found!", function));
|
||||
}
|
||||
|
||||
Scanner scanner = null;
|
||||
|
||||
try {
|
||||
return new Scanner(functionResource.getInputStream()).useDelimiter("\\A").next();
|
||||
scanner = new Scanner(functionResource.getInputStream());
|
||||
return scanner.useDelimiter("\\A").next();
|
||||
} catch (IOException e) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format("Cannot read map-reduce file %s!", function), e);
|
||||
} finally {
|
||||
if (scanner != null) {
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1814,7 +1821,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
prepareCollection(collection);
|
||||
return collection;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1840,7 +1847,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
collectionName)));
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1893,7 +1900,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1923,7 +1930,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2002,18 +2009,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the given {@link CommandResult} for erros and potentially throws an
|
||||
* {@link InvalidDataAccessApiUsageException} for that error.
|
||||
@@ -2052,6 +2047,20 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return queryMapper.getMappedSort(query.getSortObject(), mappingContext.getPersistentEntity(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to convert the given {@link RuntimeException} into a {@link DataAccessException} but returns the original
|
||||
* exception if the conversation failed. Thus allows safe re-throwing of the return value.
|
||||
*
|
||||
* @param ex the exception to translate
|
||||
* @param exceptionTranslator the {@link PersistenceExceptionTranslator} to be used for translation
|
||||
* @return
|
||||
*/
|
||||
private static RuntimeException potentiallyConvertRuntimeException(RuntimeException ex,
|
||||
PersistenceExceptionTranslator exceptionTranslator) {
|
||||
RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
}
|
||||
|
||||
// Callback implementations
|
||||
|
||||
/**
|
||||
@@ -2298,7 +2307,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
throw potentiallyConvertRuntimeException(e, exceptionTranslator);
|
||||
}
|
||||
|
||||
return cursorToUse;
|
||||
@@ -2345,20 +2354,20 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
* @since 1.7
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
static class CloseableIterableCusorAdapter<T> implements CloseableIterator<T> {
|
||||
static class CloseableIterableCursorAdapter<T> implements CloseableIterator<T> {
|
||||
|
||||
private volatile Cursor cursor;
|
||||
private PersistenceExceptionTranslator exceptionTranslator;
|
||||
private DbObjectCallback<T> objectReadCallback;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CloseableIterableCusorAdapter} backed by the given {@link Cursor}.
|
||||
* Creates a new {@link CloseableIterableCursorAdapter} backed by the given {@link Cursor}.
|
||||
*
|
||||
* @param cursor
|
||||
* @param exceptionTranslator
|
||||
* @param objectReadCallback
|
||||
*/
|
||||
public CloseableIterableCusorAdapter(Cursor cursor, PersistenceExceptionTranslator exceptionTranslator,
|
||||
public CloseableIterableCursorAdapter(Cursor cursor, PersistenceExceptionTranslator exceptionTranslator,
|
||||
DbObjectCallback<T> objectReadCallback) {
|
||||
|
||||
this.cursor = cursor;
|
||||
@@ -2376,7 +2385,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
try {
|
||||
return cursor.hasNext();
|
||||
} catch (RuntimeException ex) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2392,7 +2401,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
T converted = objectReadCallback.doWith(item);
|
||||
return converted;
|
||||
} catch (RuntimeException ex) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2403,7 +2412,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
try {
|
||||
c.close();
|
||||
} catch (RuntimeException ex) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
throw potentiallyConvertRuntimeException(ex, exceptionTranslator);
|
||||
} finally {
|
||||
cursor = null;
|
||||
exceptionTranslator = null;
|
||||
|
||||
@@ -44,9 +44,9 @@ import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigDecimalToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToNamedMongoScriptCoverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.DBObjectToStringConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.NamedMongoScriptToDBObjectConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigDecimalConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToURLConverter;
|
||||
@@ -192,8 +192,8 @@ public class CustomConversions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a conversion for the given converter. Inspects either generics or the {@link ConvertiblePair}s returned
|
||||
* by a {@link GenericConverter}.
|
||||
* Registers a conversion for the given converter. Inspects either generics of {@link Converter} and
|
||||
* {@link ConverterFactory} or the {@link ConvertiblePair}s returned by a {@link GenericConverter}.
|
||||
*
|
||||
* @param converter
|
||||
*/
|
||||
@@ -208,6 +208,10 @@ public class CustomConversions {
|
||||
for (ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||
}
|
||||
} else if (converter instanceof ConverterFactory) {
|
||||
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), ConverterFactory.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else if (converter instanceof Converter) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
|
||||
@@ -27,7 +27,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.core.index.Index.Duplicates;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.TextIndexIncludeOptions.IncludeStrategy;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
|
||||
@@ -123,6 +126,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
}
|
||||
});
|
||||
|
||||
indexInformation.addAll(resolveIndexesForDbrefs("", root.getCollection(), root));
|
||||
|
||||
return indexInformation;
|
||||
}
|
||||
|
||||
@@ -168,6 +173,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
}
|
||||
});
|
||||
|
||||
indexInformation.addAll(resolveIndexesForDbrefs(path, collection, entity));
|
||||
|
||||
return indexInformation;
|
||||
}
|
||||
|
||||
@@ -193,18 +200,19 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
return createCompoundIndexDefinitions(dotPath, collection, entity);
|
||||
}
|
||||
|
||||
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(MongoPersistentEntity<?> root) {
|
||||
private Collection<? extends IndexDefinitionHolder> potentiallyCreateTextIndexDefinition(
|
||||
MongoPersistentEntity<?> root) {
|
||||
|
||||
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder().named(root.getType()
|
||||
.getSimpleName() + "_TextIndex");
|
||||
TextIndexDefinitionBuilder indexDefinitionBuilder = new TextIndexDefinitionBuilder()
|
||||
.named(root.getType().getSimpleName() + "_TextIndex");
|
||||
|
||||
if (StringUtils.hasText(root.getLanguage())) {
|
||||
indexDefinitionBuilder.withDefaultLanguage(root.getLanguage());
|
||||
}
|
||||
|
||||
try {
|
||||
appendTextIndexInformation("", indexDefinitionBuilder, root,
|
||||
new TextIndexIncludeOptions(IncludeStrategy.DEFAULT), new CycleGuard());
|
||||
appendTextIndexInformation("", indexDefinitionBuilder, root, new TextIndexIncludeOptions(IncludeStrategy.DEFAULT),
|
||||
new CycleGuard());
|
||||
} catch (CyclicPropertyReferenceException e) {
|
||||
LOGGER.info(e.getMessage());
|
||||
}
|
||||
@@ -220,9 +228,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
}
|
||||
|
||||
private void appendTextIndexInformation(final String dotPath,
|
||||
final TextIndexDefinitionBuilder indexDefinitionBuilder, final MongoPersistentEntity<?> entity,
|
||||
final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
|
||||
private void appendTextIndexInformation(final String dotPath, final TextIndexDefinitionBuilder indexDefinitionBuilder,
|
||||
final MongoPersistentEntity<?> entity, final TextIndexIncludeOptions includeOptions, final CycleGuard guard) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
|
||||
|
||||
@@ -249,8 +256,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
TextIndexIncludeOptions optionsForNestedType = includeOptions;
|
||||
if (!IncludeStrategy.FORCE.equals(includeOptions.getStrategy()) && indexed != null) {
|
||||
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE, new TextIndexedFieldSpec(
|
||||
propertyDotPath, weight));
|
||||
optionsForNestedType = new TextIndexIncludeOptions(IncludeStrategy.FORCE,
|
||||
new TextIndexedFieldSpec(propertyDotPath, weight));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -259,9 +266,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
} catch (CyclicPropertyReferenceException e) {
|
||||
LOGGER.info(e.getMessage(), e);
|
||||
} catch (InvalidDataAccessApiUsageException e) {
|
||||
LOGGER.info(
|
||||
String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
||||
entity.getName()), e);
|
||||
LOGGER.info(String.format("Potentially invalid index structure discovered. Breaking operation for %s.",
|
||||
entity.getName()), e);
|
||||
}
|
||||
} else if (includeOptions.isForce() || indexed != null) {
|
||||
indexDefinitionBuilder.onField(propertyDotPath, weight);
|
||||
@@ -306,8 +312,8 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
protected IndexDefinitionHolder createCompoundIndexDefinition(String dotPath, String fallbackCollection,
|
||||
CompoundIndex index, MongoPersistentEntity<?> entity) {
|
||||
|
||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(resolveCompoundIndexKeyFromStringDefinition(
|
||||
dotPath, index.def()));
|
||||
CompoundIndexDefinition indexDefinition = new CompoundIndexDefinition(
|
||||
resolveCompoundIndexKeyFromStringDefinition(dotPath, index.def()));
|
||||
|
||||
if (!index.useGeneratedName()) {
|
||||
indexDefinition.named(pathAwareIndexName(index.name(), dotPath, null));
|
||||
@@ -431,13 +437,45 @@ public class MongoPersistentEntityIndexResolver implements IndexResolver {
|
||||
|
||||
if (StringUtils.hasText(dotPath)) {
|
||||
|
||||
nameToUse = StringUtils.hasText(nameToUse) ? (property != null ? dotPath.replace("." + property.getFieldName(),
|
||||
"") : dotPath) + "." + nameToUse : dotPath;
|
||||
nameToUse = StringUtils.hasText(nameToUse)
|
||||
? (property != null ? dotPath.replace("." + property.getFieldName(), "") : dotPath) + "." + nameToUse
|
||||
: dotPath;
|
||||
}
|
||||
return nameToUse;
|
||||
|
||||
}
|
||||
|
||||
private List<IndexDefinitionHolder> resolveIndexesForDbrefs(final String path, final String collection,
|
||||
MongoPersistentEntity<?> entity) {
|
||||
|
||||
final List<IndexDefinitionHolder> indexes = new ArrayList<IndexDefinitionHolder>(0);
|
||||
entity.doWithAssociations(new AssociationHandler<MongoPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithAssociation(Association<MongoPersistentProperty> association) {
|
||||
|
||||
MongoPersistentProperty property = association.getInverse();
|
||||
|
||||
String propertyDotPath = (StringUtils.hasText(path) ? path + "." : "") + property.getFieldName();
|
||||
|
||||
if (property.isAnnotationPresent(GeoSpatialIndexed.class) || property.isAnnotationPresent(TextIndexed.class)) {
|
||||
throw new MappingException(
|
||||
String.format("Cannot create geospatial-/text- index on DBRef in collection '%s' for path '%s'.",
|
||||
collection, propertyDotPath));
|
||||
}
|
||||
|
||||
IndexDefinitionHolder indexDefinitionHolder = createIndexDefinitionHolderForProperty(propertyDotPath,
|
||||
collection, property);
|
||||
|
||||
if (indexDefinitionHolder != null) {
|
||||
indexes.add(indexDefinitionHolder);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return indexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link CycleGuard} holds information about properties and the paths for accessing those. This information is used
|
||||
* to detect potential cycles within the references.
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.mongodb.WriteConcern;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Christoph Strobl
|
||||
* @author Viktor Khoroshko
|
||||
*/
|
||||
public class MongoDbFactoryParserIntegrationTests {
|
||||
|
||||
@@ -198,6 +199,52 @@ public class MongoDbFactoryParserIntegrationTests {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test
|
||||
public void setsUpClientUriWithId() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-and-id.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("testMongo");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test
|
||||
public void setsUpUriWithId() {
|
||||
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-uri-and-id.xml"));
|
||||
BeanDefinition definition = factory.getBeanDefinition("testMongo");
|
||||
ConstructorArgumentValues constructorArguments = definition.getConstructorArgumentValues();
|
||||
|
||||
assertThat(constructorArguments.getArgumentCount(), is(1));
|
||||
ValueHolder argument = constructorArguments.getArgumentValue(0, MongoClientURI.class);
|
||||
assertThat(argument, is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsClientUriPlusDetailedConfigurationAndWriteConcern() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-write-concern-and-details.xml"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1293
|
||||
*/
|
||||
@Test(expected = BeanDefinitionParsingException.class)
|
||||
public void rejectsUriPlusDetailedConfigurationAndWriteConcern() {
|
||||
reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-client-uri-write-concern-and-details.xml"));
|
||||
}
|
||||
|
||||
private static void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) {
|
||||
|
||||
SimpleMongoDbFactory dbFactory = ctx.getBean("first", SimpleMongoDbFactory.class);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2015 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.mongodb.core;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
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.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate.CloseableIterableCursorAdapter;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate.DbObjectCallback;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
|
||||
import com.mongodb.Cursor;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CloseableIterableCursorAdapter}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CloseableIterableCursorAdapterUnitTests {
|
||||
|
||||
@Mock PersistenceExceptionTranslator exceptionTranslator;
|
||||
@Mock DbObjectCallback<Object> callback;
|
||||
|
||||
Cursor cursor;
|
||||
CloseableIterator<Object> adapter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.cursor = doThrow(IllegalArgumentException.class).when(mock(Cursor.class));
|
||||
this.adapter = new CloseableIterableCursorAdapter<Object>(cursor, exceptionTranslator, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void propagatesOriginalExceptionFromAdapterDotNext() {
|
||||
|
||||
cursor.next();
|
||||
adapter.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void propagatesOriginalExceptionFromAdapterDotHasNext() {
|
||||
|
||||
cursor.hasNext();
|
||||
adapter.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1276
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void propagatesOriginalExceptionFromAdapterDotClose() {
|
||||
|
||||
cursor.close();
|
||||
adapter.close();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
* Copyright 2011-2015 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.
|
||||
@@ -21,7 +21,9 @@ import static org.junit.Assert.*;
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.Format;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
@@ -32,8 +34,10 @@ import org.joda.time.DateTime;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
|
||||
@@ -43,12 +47,11 @@ import com.mongodb.DBRef;
|
||||
* Unit tests for {@link CustomConversions}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @auhtor Christoph Strobl
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class CustomConversionsUnitTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void findsBasicReadAndWriteConversions() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Arrays.asList(FormatToStringConverter.INSTANCE,
|
||||
@@ -62,7 +65,6 @@ public class CustomConversionsUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void considersSubtypesCorrectly() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Arrays.asList(NumberToStringConverter.INSTANCE,
|
||||
@@ -132,6 +134,7 @@ public class CustomConversionsUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void doesNotConsiderTypeSimpleIfOnlyReadConverterIsRegistered() {
|
||||
|
||||
CustomConversions conversions = new CustomConversions(Arrays.asList(StringToFormatConverter.INSTANCE));
|
||||
assertThat(conversions.isSimpleType(Format.class), is(false));
|
||||
}
|
||||
@@ -257,6 +260,17 @@ public class CustomConversionsUnitTests {
|
||||
assertThat(customConversions.hasCustomWriteTarget(LocalDateTime.class), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1302
|
||||
*/
|
||||
@Test
|
||||
public void registersConverterFactoryCorrectly() {
|
||||
|
||||
CustomConversions customConversions = new CustomConversions(Collections.singletonList(new FormatConverterFactory()));
|
||||
|
||||
assertThat(customConversions.getCustomWriteTarget(String.class, SimpleDateFormat.class), notNullValue());
|
||||
}
|
||||
|
||||
private static Class<?> createProxyTypeFor(Class<?> type) {
|
||||
|
||||
ProxyFactory factory = new ProxyFactory();
|
||||
@@ -331,4 +345,37 @@ public class CustomConversionsUnitTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
static class FormatConverterFactory implements ConverterFactory<String, Format> {
|
||||
|
||||
@Override
|
||||
public <T extends Format> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToFormat<T>(targetType);
|
||||
}
|
||||
|
||||
private static final class StringToFormat<T extends Format> implements Converter<String, T> {
|
||||
|
||||
private final Class<T> targetType;
|
||||
|
||||
public StringToFormat(Class<T> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convert(String source) {
|
||||
|
||||
if (source.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return targetType.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.DBObjectTestUtils;
|
||||
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
|
||||
@@ -148,6 +149,34 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("CollectionOverride"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1297
|
||||
*/
|
||||
@Test
|
||||
public void resolvesIndexOnDbrefWhenDefined() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WithDbRef.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("withDbRef"));
|
||||
assertThat(indexDefinitions.get(0).getIndexKeys(), equalTo(new BasicDBObjectBuilder().add("indexedDbRef", 1)
|
||||
.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1297
|
||||
*/
|
||||
@Test
|
||||
public void resolvesIndexOnDbrefWhenDefinedOnNestedElement() {
|
||||
|
||||
List<IndexDefinitionHolder> indexDefinitions = prepareMappingContextAndResolveIndexForType(WrapperOfWithDbRef.class);
|
||||
|
||||
assertThat(indexDefinitions, hasSize(1));
|
||||
assertThat(indexDefinitions.get(0).getCollection(), equalTo("wrapperOfWithDbRef"));
|
||||
assertThat(indexDefinitions.get(0).getIndexKeys(),
|
||||
equalTo(new BasicDBObjectBuilder().add("nested.indexedDbRef", 1).get()));
|
||||
}
|
||||
|
||||
@Document(collection = "Zero")
|
||||
static class IndexOnLevelZero {
|
||||
@Indexed String indexedProperty;
|
||||
@@ -182,6 +211,24 @@ public class MongoPersistentEntityIndexResolverUnitTests {
|
||||
@Indexed @Field("customFieldName") String namedProperty;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class WrapperOfWithDbRef {
|
||||
WithDbRef nested;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class WithDbRef {
|
||||
|
||||
@Indexed//
|
||||
@DBRef//
|
||||
NoIndex indexedDbRef;
|
||||
}
|
||||
|
||||
@Document(collection = "no-index")
|
||||
static class NoIndex {
|
||||
@Id String id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory id="testMongo" client-uri="mongodb://username:password@localhost/database" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory client-uri="mongodb://username:password@localhost/database" write-concern="NORMAL" username="username" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory id="testMongo" uri="mongodb://username:password@localhost/database" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<mongo:db-factory uri="mongodb://username:password@localhost/database" write-concern="NORMAL" username="username" />
|
||||
|
||||
</beans>
|
||||
@@ -1,6 +1,21 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================
|
||||
|
||||
Changes in version 1.8.1.RELEASE (2015-11-15)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1316 - Release 1.8.1 (Gosling).
|
||||
* DATAMONGO-1312 - Cannot convert generic sub-document fields.
|
||||
* DATAMONGO-1302 - CustomConversions should allow registration of ConverterFactory.
|
||||
* DATAMONGO-1297 - Unique Index on DBRef.
|
||||
* DATAMONGO-1293 - MongoDbFactoryParser should allow id attribute in addition to client-uri.
|
||||
* DATAMONGO-1276 - MongoTemplate.CloseableIterableCursorAdapter does not null check return values from PersistenceExceptionTranslator.
|
||||
|
||||
|
||||
Changes in version 1.6.4.RELEASE (2015-10-14)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1304 - Release 1.6.4 (Evans).
|
||||
|
||||
|
||||
Changes in version 1.8.0.RELEASE (2015-09-01)
|
||||
---------------------------------------------
|
||||
* DATAMONGO-1282 - Release 1.8 GA (Gosling).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Spring Data MongoDB 1.8 GA
|
||||
Spring Data MongoDB 1.8.1
|
||||
Copyright (c) [2010-2015] Pivotal Software, Inc.
|
||||
|
||||
This product is licensed to you under the Apache License, Version 2.0 (the "License").
|
||||
|
||||
Reference in New Issue
Block a user