diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index f444aae7b..96564ffed 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -17,6 +17,7 @@ 1.0.0.GA + 1.3 @@ -119,6 +120,13 @@ ${validation} true + + + org.objenesis + objenesis + ${objenesis} + true + org.hibernate diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java new file mode 100644 index 000000000..8835009b1 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/LazyLoadingException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb; + +import org.springframework.dao.UncategorizedDataAccessException; + +/** + * @author Oliver Gierke + */ +public class LazyLoadingException extends UncategorizedDataAccessException { + + private static final long serialVersionUID = -7089224903873220037L; + + /** + * @param msg + * @param cause + */ + public LazyLoadingException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java index 687fc6943..6e760e6a5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/MongoDbFactory.java @@ -16,6 +16,7 @@ package org.springframework.data.mongodb; import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.mongodb.core.MongoExceptionTranslator; import com.mongodb.DB; @@ -48,7 +49,7 @@ public interface MongoDbFactory { /** * Exposes a shared {@link MongoExceptionTranslator}. * - * @return + * @return will never be {@literal null}. */ - MongoExceptionTranslator getExceptionTranslator(); + PersistenceExceptionTranslator getExceptionTranslator(); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java index 8ebddf1bb..51046e33f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java @@ -31,6 +31,8 @@ import org.springframework.data.mapping.context.MappingContextIsNewStrategyFacto import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import org.springframework.data.mongodb.core.convert.CustomConversions; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.mapping.CamelCaseAbbreviatingFieldNamingStrategy; import org.springframework.data.mongodb.core.mapping.Document; @@ -178,8 +180,11 @@ public abstract class AbstractMongoConfiguration { */ @Bean public MappingMongoConverter mappingMongoConverter() throws Exception { - MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), mongoMappingContext()); + + DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory()); + MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mongoMappingContext()); converter.setCustomConversions(customConversions()); + return converter; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 330c63ea7..656020c12 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -46,6 +46,7 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.OptimisticLockingFailureException; +import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.authentication.UserCredentials; import org.springframework.data.convert.EntityReader; import org.springframework.data.mapping.PersistentEntity; @@ -59,6 +60,8 @@ import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.Fields; import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.convert.MongoWriter; @@ -145,6 +148,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { private final MongoConverter mongoConverter; private final MappingContext, MongoPersistentProperty> mappingContext; private final MongoDbFactory mongoDbFactory; + private final PersistenceExceptionTranslator exceptionTranslator; private final QueryMapper queryMapper; private final UpdateMapper updateMapper; @@ -198,6 +202,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { Assert.notNull(mongoDbFactory); this.mongoDbFactory = mongoDbFactory; + this.exceptionTranslator = mongoDbFactory.getExceptionTranslator(); this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter(mongoDbFactory) : mongoConverter; this.queryMapper = new QueryMapper(this.mongoConverter); this.updateMapper = new UpdateMapper(this.mongoConverter); @@ -1796,7 +1801,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { * @return */ private RuntimeException potentiallyConvertRuntimeException(RuntimeException ex) { - RuntimeException resolved = this.mongoDbFactory.getExceptionTranslator().translateExceptionIfPossible(ex); + RuntimeException resolved = this.exceptionTranslator.translateExceptionIfPossible(ex); return resolved == null ? ex : resolved; } @@ -1822,7 +1827,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { } private static final MongoConverter getDefaultMongoConverter(MongoDbFactory factory) { - MappingMongoConverter converter = new MappingMongoConverter(factory, new MongoMappingContext()); + + DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); + MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); converter.afterPropertiesSet(); return converter; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java index 658c34ccd..116676b5f 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import java.net.UnknownHostException; import org.springframework.beans.factory.DisposableBean; import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.data.authentication.UserCredentials; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.util.Assert; @@ -34,7 +35,7 @@ import com.mongodb.WriteConcern; * * @author Mark Pollack * @author Oliver Gierke - * @author Thomas Darimont + * @author Thomas Darimont */ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { @@ -42,8 +43,8 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { private final String databaseName; private final boolean mongoInstanceCreated; private final UserCredentials credentials; + private final PersistenceExceptionTranslator exceptionTranslator; private WriteConcern writeConcern; - private final MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); /** * Create an instance of {@link SimpleMongoDbFactory} given the {@link Mongo} instance and database name. @@ -74,6 +75,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { * @throws UnknownHostException * @see MongoURI */ + @SuppressWarnings("deprecation") public SimpleMongoDbFactory(MongoURI uri) throws MongoException, UnknownHostException { this(new Mongo(uri), uri.getDatabase(), new UserCredentials(uri.getUsername(), parseChars(uri.getPassword())), true); } @@ -90,6 +92,7 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { this.databaseName = databaseName; this.mongoInstanceCreated = mongoInstanceCreated; this.credentials = credentials == null ? UserCredentials.NO_CREDENTIALS : credentials; + this.exceptionTranslator = new MongoExceptionTranslator(); } /** @@ -140,12 +143,13 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory { private static String parseChars(char[] chars) { return chars == null ? null : String.valueOf(chars); } - - /* (non-Javadoc) - * @see org.springframework.data.mongodb.MongoDbFactory#getExceptionTranslator() - */ - @Override - public MongoExceptionTranslator getExceptionTranslator() { - return this.exceptionTranslator; - } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.MongoDbFactory#getExceptionTranslator() + */ + @Override + public PersistenceExceptionTranslator getExceptionTranslator() { + return this.exceptionTranslator; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java index 7d84a3254..a6afaa920 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolver.java @@ -15,19 +15,34 @@ */ package org.springframework.data.mongodb.core.convert; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import com.mongodb.DBRef; + /** * Used to resolve associations annotated with {@link org.springframework.data.mongodb.core.mapping.DBRef}. * * @author Thomas Darimont */ -interface DbRefResolver { +public interface DbRefResolver { + + /** + * @param property will never be {@literal null}. + * @param callback will never be {@literal null}. + * @return + */ + Object resolveDbRef(MongoPersistentProperty property, DbRefResolverCallback callback); /** - * @param property - * @param callback + * Creates a {@link DBRef} instance for the given {@link org.springframework.data.mongodb.core.mapping.DBRef} + * annotation, {@link MongoPersistentEntity} and id. + * + * @param annotation will never be {@literal null}. + * @param entity will never be {@literal null}. + * @param id will never be {@literal null}. * @return */ - Object resolve(MongoPersistentProperty property, DbRefResolveCallback callback); + DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef annotation, MongoPersistentEntity entity, + Object id); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolveCallback.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java similarity index 82% rename from spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolveCallback.java rename to spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java index 5326610ca..a33264f91 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolveCallback.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DbRefResolverCallback.java @@ -21,11 +21,14 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; * Callback interface to be used in conjunction with {@link DbRefResolver}. * * @author Thomas Darimont + * @author Oliver Gierke */ -interface DbRefResolveCallback { +public interface DbRefResolverCallback { /** - * @param property + * Resolve the final object for the given {@link MongoPersistentProperty}. + * + * @param property will never be {@literal null}. * @return */ Object resolve(MongoPersistentProperty property); diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java new file mode 100644 index 000000000..899417aae --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java @@ -0,0 +1,256 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.convert; + +import java.lang.reflect.Method; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.objenesis.Objenesis; +import org.objenesis.ObjenesisStd; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.cglib.proxy.Callback; +import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.Factory; +import org.springframework.cglib.proxy.MethodProxy; +import org.springframework.core.SpringVersion; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.data.mongodb.LazyLoadingException; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +import com.mongodb.DB; +import com.mongodb.DBRef; + +/** + * A {@link DbRefResolver} that resolves {@link org.springframework.data.mongodb.core.mapping.DBRef}s by delegating to a + * {@link DbRefResolverCallback} than is able to generate lazy loading proxies. + * + * @author Thomas Darimont + * @author Oliver Gierke + */ +public class DefaultDbRefResolver implements DbRefResolver { + + private static final boolean IS_SPRING_4_OR_BETTER = SpringVersion.getVersion().startsWith("4"); + private static final boolean OBJENESIS_PRESENT = ClassUtils.isPresent("org.objenesis.Objenesis", null); + + private final MongoDbFactory mongoDbFactory; + private final PersistenceExceptionTranslator exceptionTranslator; + + /** + * Creates a new {@link DefaultDbRefResolver} with the given {@link MongoDbFactory}. + * + * @param mongoDbFactory must not be {@literal null}. + */ + public DefaultDbRefResolver(MongoDbFactory mongoDbFactory) { + + Assert.notNull(mongoDbFactory, "MongoDbFactory translator must not be null!"); + + this.mongoDbFactory = mongoDbFactory; + this.exceptionTranslator = mongoDbFactory.getExceptionTranslator(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.convert.DbRefResolver#resolveDbRef(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.convert.DbRefResolverCallback) + */ + @Override + public Object resolveDbRef(MongoPersistentProperty property, DbRefResolverCallback callback) { + + Assert.notNull(property, "Property must not be null!"); + Assert.notNull(callback, "Callback must not be null!"); + + if (isLazyDbRef(property)) { + return createLazyLoadingProxy(property, callback); + } + + return callback.resolve(property); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.core.convert.DbRefResolver#created(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.mapping.MongoPersistentEntity, java.lang.Object) + */ + @Override + public DBRef createDbRef(org.springframework.data.mongodb.core.mapping.DBRef annotation, + MongoPersistentEntity entity, Object id) { + + DB db = mongoDbFactory.getDb(); + db = annotation != null && StringUtils.hasText(annotation.db()) ? mongoDbFactory.getDb(annotation.db()) : db; + + return new DBRef(db, entity.getCollection(), id); + } + + /** + * Creates a proxy for the given {@link MongoPersistentProperty} using the given {@link DbRefResolverCallback} to + * eventually resolve the value of the property. + * + * @param property must not be {@literal null}. + * @param callback must not be {@literal null}. + * @return + */ + private Object createLazyLoadingProxy(MongoPersistentProperty property, DbRefResolverCallback callback) { + + ProxyFactory proxyFactory = new ProxyFactory(); + Class propertyType = property.getType(); + + for (Class type : propertyType.getInterfaces()) { + proxyFactory.addInterface(type); + } + + LazyLoadingInterceptor interceptor = new LazyLoadingInterceptor(property, exceptionTranslator, callback); + + if (propertyType.isInterface()) { + proxyFactory.addInterface(propertyType); + proxyFactory.addAdvice(interceptor); + return proxyFactory.getProxy(); + } + + proxyFactory.setProxyTargetClass(true); + proxyFactory.setTargetClass(propertyType); + + if (IS_SPRING_4_OR_BETTER || !OBJENESIS_PRESENT) { + proxyFactory.addAdvice(interceptor); + return proxyFactory.getProxy(); + } + + return ObjenesisProxyEnhancer.enhanceAndGet(proxyFactory, propertyType, interceptor); + } + + /** + * @param property + * @return + */ + private boolean isLazyDbRef(MongoPersistentProperty property) { + return property.getDBRef() != null && property.getDBRef().lazy(); + } + + /** + * A {@link MethodInterceptor} that is used within a lazy loading proxy. The property resolving is delegated to a + * {@link DbRefResolverCallback}. The resolving process is triggered by a method invocation on the proxy and is + * guaranteed to be performed only once. + * + * @author Thomas Darimont + */ + static class LazyLoadingInterceptor implements MethodInterceptor, org.springframework.cglib.proxy.MethodInterceptor { + + private final DbRefResolverCallback callback; + private final MongoPersistentProperty property; + private final PersistenceExceptionTranslator exceptionTranslator; + + private volatile boolean resolved; + private Object result; + + /** + * Creates a new {@link LazyLoadingInterceptor} for the given {@link MongoPersistentProperty}, + * {@link PersistenceExceptionTranslator} and {@link DbRefResolverCallback}. + * + * @param property must not be {@literal null}. + * @param callback must not be {@literal null}. + */ + public LazyLoadingInterceptor(MongoPersistentProperty property, PersistenceExceptionTranslator exceptionTranslator, + DbRefResolverCallback callback) { + + Assert.notNull(property, "Property must not be null!"); + Assert.notNull(exceptionTranslator, "Exception translator must not be null!"); + Assert.notNull(callback, "Callback must not be null!"); + + this.callback = callback; + this.exceptionTranslator = exceptionTranslator; + this.property = property; + } + + /* + * (non-Javadoc) + * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) + */ + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + return intercept(invocation.getThis(), invocation.getMethod(), invocation.getArguments(), null); + } + + /* + * (non-Javadoc) + * @see org.springframework.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], org.springframework.cglib.proxy.MethodProxy) + */ + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + + if (!resolved) { + this.result = resolve(); + this.resolved = true; + } + + return method.invoke(result, args); + } + + /** + * @return + */ + private synchronized Object resolve() { + + if (!resolved) { + + try { + + return callback.resolve(property); + + } catch (RuntimeException ex) { + + DataAccessException translatedException = this.exceptionTranslator.translateExceptionIfPossible(ex); + throw new LazyLoadingException("Unable to lazily resolve DBRef!", translatedException); + } + } + + return result; + } + + public boolean isResolved() { + return resolved; + } + + public Object getResult() { + return result; + } + } + + /** + * Static class to accomodate optional dependency on Objenesis. + * + * @author Oliver Gierke + */ + private static class ObjenesisProxyEnhancer { + + private static final Objenesis OBJENESIS = new ObjenesisStd(true); + + public static Object enhanceAndGet(ProxyFactory proxyFactory, Class type, + org.springframework.cglib.proxy.MethodInterceptor interceptor) { + + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(type); + enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class); + + Factory factory = (Factory) OBJENESIS.newInstance(enhancer.createClass()); + factory.setCallbacks(new Callback[] { interceptor }); + return factory; + } + } +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index 81b70d8e3..0d5e398df 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -24,11 +24,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -36,7 +33,6 @@ import org.springframework.core.CollectionFactory; import org.springframework.core.convert.ConversionException; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.ConversionServiceFactory; -import org.springframework.dao.DataAccessException; import org.springframework.data.convert.EntityInstantiator; import org.springframework.data.convert.TypeMapper; import org.springframework.data.mapping.Association; @@ -61,11 +57,9 @@ import org.springframework.data.util.TypeInformation; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; -import com.mongodb.DB; import com.mongodb.DBObject; import com.mongodb.DBRef; @@ -84,38 +78,49 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App protected final MappingContext, MongoPersistentProperty> mappingContext; protected final SpelExpressionParser spelExpressionParser = new SpelExpressionParser(); - protected final MongoDbFactory mongoDbFactory; protected final QueryMapper idMapper; + protected final DbRefResolver dbRefResolver; protected ApplicationContext applicationContext; protected boolean useFieldAccessOnly = true; protected MongoTypeMapper typeMapper; protected String mapKeyDotReplacement = null; - protected DbRefResolver dbRefResolver; private SpELContext spELContext; /** - * Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}. + * Creates a new {@link MappingMongoConverter} given the new {@link DbRefResolver} and {@link MappingContext}. * * @param mongoDbFactory must not be {@literal null}. * @param mappingContext must not be {@literal null}. */ @SuppressWarnings("deprecation") - public MappingMongoConverter(MongoDbFactory mongoDbFactory, + public MappingMongoConverter(DbRefResolver dbRefResolver, MappingContext, MongoPersistentProperty> mappingContext) { super(ConversionServiceFactory.createDefaultConversionService()); - Assert.notNull(mongoDbFactory); - Assert.notNull(mappingContext); + Assert.notNull(dbRefResolver, "DbRefResolver must not be null!"); + Assert.notNull(mappingContext, "MappingContext must not be null!"); - this.mongoDbFactory = mongoDbFactory; + this.dbRefResolver = dbRefResolver; this.mappingContext = mappingContext; this.typeMapper = new DefaultMongoTypeMapper(DefaultMongoTypeMapper.DEFAULT_TYPE_KEY, mappingContext); this.idMapper = new QueryMapper(this); this.spELContext = new SpELContext(DBObjectPropertyAccessor.INSTANCE); - this.dbRefResolver = new DelegatingDbRefResolver(); + } + + /** + * Creates a new {@link MappingMongoConverter} given the new {@link MongoDbFactory} and {@link MappingContext}. + * + * @deprecated use the constructor taking a {@link DbRefResolver} instead. + * @param mongoDbFactory must not be {@literal null}. + * @param mappingContext must not be {@literal null}. + */ + @Deprecated + public MappingMongoConverter(MongoDbFactory mongoDbFactory, + MappingContext, MongoPersistentProperty> mappingContext) { + this(new DefaultDbRefResolver(mongoDbFactory), mappingContext); } /** @@ -270,17 +275,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App MongoPersistentProperty inverseProp = association.getInverse(); - Object obj = dbRefResolver.resolve(inverseProp, new AbstractDbRefResolveCallback(mongoDbFactory) { + Object obj = dbRefResolver.resolveDbRef(inverseProp, new DbRefResolverCallback() { @Override - public Object doResolve(MongoPersistentProperty property) { + public Object resolve(MongoPersistentProperty property) { return getValueInternal(property, dbo, evaluator, parent); } }); wrapper.setProperty(inverseProp, obj); } - }); return result; @@ -764,10 +768,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App throw new MappingException("Cannot create a reference to an object with a NULL id."); } - DB db = mongoDbFactory.getDb(); - db = dbref != null && StringUtils.hasText(dbref.db()) ? mongoDbFactory.getDb(dbref.db()) : db; - - return new DBRef(db, targetEntity.getCollection(), idMapper.convertId(id)); + return dbRefResolver.createDbRef(dbref, targetEntity, idMapper.convertId(id)); } protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, SpELExpressionEvaluator eval, @@ -1084,184 +1085,4 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App DBObject readRef(DBRef ref) { return ref.fetch(); } - - /** - * @author Thomas Darimont - */ - static abstract class AbstractDbRefResolveCallback implements DbRefResolveCallback { - - private final MongoDbFactory mongoDbFactory; - - /** - * @param mongoDbFactory - */ - public AbstractDbRefResolveCallback(MongoDbFactory mongoDbFactory) { - this.mongoDbFactory = mongoDbFactory; - } - - /* (non-Javadoc) - * @see org.springframework.data.mongodb.core.convert.DbRefResolveCallback#resolve(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty) - */ - @Override - public Object resolve(MongoPersistentProperty property) { - try { - return doResolve(property); - } catch (RuntimeException ex) { - DataAccessException tex = mongoDbFactory.getExceptionTranslator().translateExceptionIfPossible(ex); - throw tex != null ? tex : ex; - } - } - - /** - * @param property - * @return - */ - protected abstract Object doResolve(MongoPersistentProperty property); - } - - /** - * A marker interface that is used to mark lazy loading proxies. - * - * @author Thomas Darimont - */ - public static interface LazyLoadingProxy {} - - /** - * A {@link MethodInterceptor} that is used within a lazy loading proxy. The property resolving is delegated to a - * {@link DbRefResolveCallback}. The resolving process is triggered by a method invocation on the proxy and is - * guaranteed to be performed only once. - * - * @author Thomas Darimont - */ - public static class LazyLoadingInterceptor implements MethodInterceptor { - - private DbRefResolveCallback callback; - - private MongoPersistentProperty property; - - private volatile boolean resolved; - - private Object result; - - /** - * @param callback - * @param property - */ - public LazyLoadingInterceptor(DbRefResolveCallback callback, MongoPersistentProperty property) { - - this.callback = callback; - this.property = property; - } - - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - - if (!resolved) { - this.result = resolve(); - this.resolved = true; - } - - return invocation.getMethod().invoke(result, invocation.getArguments()); - } - - /** - * @return - */ - private synchronized Object resolve() { - - if (!resolved) { - - try { - return callback.resolve(property); - } catch (Exception ex) { - throw new RuntimeException("Could not resolve lazy DBRef: " + property, ex); - } finally { - cleanup(); - } - } - - return result; - } - - /** - * Visible for testing. - * - * @return - */ - public boolean isResolved() { - return resolved; - } - - /** - * Visible for testing. - * - * @return the result - */ - public Object getResult() { - return result; - } - - /** - * Cleans up unnecessary references to avoid memory leaks. - */ - private void cleanup() { - - this.callback = null; - this.property = null; - } - } - - /** - * A {@link DbRefResolver} that resolves {@link org.springframework.data.mongodb.core.mapping.DBRef}s by delegating to - * a {@link DbRefResolveCallback} than is able to generate lazy loading proxies. - * - * @author Thomas Darimont - */ - static class DelegatingDbRefResolver implements DbRefResolver { - - /* (non-Javadoc) - * @see org.springframework.data.mongodb.core.convert.DbRefResolver#resolve(org.springframework.data.mongodb.core.mapping.MongoPersistentProperty, org.springframework.data.mongodb.core.convert.DbRefResolveCallback) - */ - public Object resolve(MongoPersistentProperty property, DbRefResolveCallback callback) { - - Assert.notNull(property, "property must not be null!"); - Assert.notNull(callback, "callback must not be null!"); - - if (isLazyDbRef(property)) { - return createLazyLoadingProxy(property, callback); - } - - return callback.resolve(property); - } - - /** - * @param property - * @param callback - * @return - */ - public Object createLazyLoadingProxy(MongoPersistentProperty property, DbRefResolveCallback callback) { - - ProxyFactory proxyFactory = new ProxyFactory(); - - if (property.getRawType().isInterface()) { - proxyFactory.addInterface(property.getRawType()); - } else { - proxyFactory.setProxyTargetClass(true); - proxyFactory.setTargetClass(property.getRawType()); - } - - proxyFactory.addInterface(LazyLoadingProxy.class); - proxyFactory.addAdvice(new LazyLoadingInterceptor(callback, property)); - - return proxyFactory.getProxy(); - } - - /** - * @param property - * @return - */ - protected boolean isLazyDbRef(MongoPersistentProperty property) { - return property.getDBRef() != null && property.getDBRef().lazy(); - } - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java new file mode 100644 index 000000000..69b029735 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.config; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.DataAccessException; +import org.springframework.data.mongodb.core.CollectionCallback; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.Mongo; +import com.mongodb.MongoClient; +import com.mongodb.MongoException; + +/** + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public abstract class AbstractIntegrationTests { + + @Configuration + static class TestConfig extends AbstractMongoConfiguration { + + @Override + protected String getDatabaseName() { + return "database"; + } + + @Override + public Mongo mongo() throws Exception { + return new MongoClient(); + } + } + + @Autowired MongoOperations operations; + + @Before + @After + public void cleanUp() { + + for (String collectionName : operations.getCollectionNames()) { + if (!collectionName.startsWith("system")) { + operations.execute(collectionName, new CollectionCallback() { + @Override + public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException { + collection.remove(new BasicDBObject()); + assertThat(collection.find().hasNext(), is(false)); + return null; + } + }); + } + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index 18ba7f135..ddb85084e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.AbstractApplicationContext; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoTypeMapper; @@ -35,6 +36,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.Mongo; +import com.mongodb.MongoClient; /** * Unit tests for {@link AbstractMongoConfiguration}. @@ -84,12 +86,13 @@ public class AbstractMongoConfigurationUnitTests { @Test public void containsMongoDbFactoryButNoMongoBean() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); + AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); assertThat(context.getBean(MongoDbFactory.class), is(notNullValue())); exception.expect(NoSuchBeanDefinitionException.class); context.getBean(Mongo.class); + context.close(); } @Test @@ -109,12 +112,13 @@ public class AbstractMongoConfigurationUnitTests { @Test public void lifecycleCallbacksAreInvokedInAppropriateOrder() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); + AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class); BasicMongoPersistentEntity entity = mappingContext.getPersistentEntity(Entity.class); StandardEvaluationContext spElContext = (StandardEvaluationContext) ReflectionTestUtils.getField(entity, "context"); assertThat(spElContext.getBeanResolver(), is(notNullValue())); + context.close(); } /** @@ -123,12 +127,13 @@ public class AbstractMongoConfigurationUnitTests { @Test public void shouldBeAbleToConfigureCustomTypeMapperViaJavaConfig() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); + AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class); MongoTypeMapper typeMapper = context.getBean(CustomMongoTypeMapper.class); MappingMongoConverter mmc = context.getBean(MappingMongoConverter.class); assertThat(mmc, is(notNullValue())); assertThat(mmc.getTypeMapper(), is(typeMapper)); + context.close(); } private static void assertScanningDisabled(final String value) throws ClassNotFoundException { @@ -154,7 +159,7 @@ public class AbstractMongoConfigurationUnitTests { @Override public Mongo mongo() throws Exception { - return new Mongo(); + return new MongoClient(); } @Bean diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java index 108c73b53..0a49cef53 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import static org.junit.Assert.*; import org.joda.time.DateTime; import org.junit.Test; -import org.springframework.context.ApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Id; @@ -37,7 +37,7 @@ public class AuditingIntegrationTests { @Test public void enablesAuditingAndSetsPropertiesAccordingly() { - ApplicationContext context = new ClassPathXmlApplicationContext("auditing.xml", getClass()); + AbstractApplicationContext context = new ClassPathXmlApplicationContext("auditing.xml", getClass()); Entity entity = new Entity(); BeforeConvertEvent event = new BeforeConvertEvent(entity); @@ -52,17 +52,13 @@ public class AuditingIntegrationTests { assertThat(entity.created, is(notNullValue())); assertThat(entity.modified, is(not(entity.created))); + context.close(); } class Entity { - @CreatedDate - DateTime created; - - @LastModifiedDate - DateTime modified; - - @Id - Long id; + @CreatedDate DateTime created; + @LastModifiedDate DateTime modified; + @Id Long id; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java index 899e5c84c..7aeb09014 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2011 by the original author(s). + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -27,7 +27,7 @@ import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; -import org.springframework.context.ApplicationContext; +import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.data.mongodb.MongoDbFactory; @@ -36,6 +36,7 @@ import org.springframework.test.util.ReflectionTestUtils; import com.mongodb.DB; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoURI; import com.mongodb.WriteConcern; @@ -57,9 +58,11 @@ public class MongoDbFactoryParserIntegrationTests { @Test public void testWriteConcern() throws Exception { - SimpleMongoDbFactory dbFactory = new SimpleMongoDbFactory(new Mongo("localhost"), "database"); + + SimpleMongoDbFactory dbFactory = new SimpleMongoDbFactory(new MongoClient("localhost"), "database"); dbFactory.setWriteConcern(WriteConcern.SAFE); dbFactory.getDb(); + assertThat(ReflectionTestUtils.getField(dbFactory, "writeConcern"), is((Object) WriteConcern.SAFE)); } @@ -82,11 +85,13 @@ public class MongoDbFactoryParserIntegrationTests { @Test public void readsReplicasWriteConcernCorrectly() { - ApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean-custom-write-concern.xml"); + AbstractApplicationContext ctx = new ClassPathXmlApplicationContext( + "namespace/db-factory-bean-custom-write-concern.xml"); MongoDbFactory factory = ctx.getBean("second", MongoDbFactory.class); DB db = factory.getDb(); assertThat(db.getWriteConcern(), is(WriteConcern.REPLICAS_SAFE)); + ctx.close(); } private void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index 96a52bb95..c68fbfd13 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -18,8 +18,8 @@ package org.springframework.data.mongodb.config; import static org.junit.Assert.*; import static org.springframework.test.util.ReflectionTestUtils.*; -import javax.net.ssl.SSLSocketFactory; - +import javax.net.ssl.SSLSocketFactory; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -43,13 +43,13 @@ import com.mongodb.WriteConcern; * @author Mark Pollack * @author Oliver Gierke * @author Martin Baumgartner - * @author Thomas Darimont + * @author Thomas Darimont */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class MongoNamespaceTests { - @Autowired private ApplicationContext ctx; + @Autowired ApplicationContext ctx; @Test public void testMongoSingleton() throws Exception { @@ -61,46 +61,46 @@ public class MongoNamespaceTests { @Test public void testMongoSingletonWithAttributes() throws Exception { - + assertTrue(ctx.containsBean("defaultMongo")); MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&defaultMongo"); String host = (String) getField(mfb, "host"); Integer port = (Integer) getField(mfb, "port"); assertEquals("localhost", host); assertEquals(new Integer(27017), port); - - MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); - assertFalse("By default socketFactory should not be a SSLSocketFactory", - options.getSocketFactory() instanceof SSLSocketFactory); - } - - /** - * @see DATAMONGO-764 - */ - @Test - public void testMongoSingletonWithSslEnabled() throws Exception { - - assertTrue(ctx.containsBean("mongoSsl")); - MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&mongoSsl"); - - MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); - assertTrue("socketFactory should be a SSLSocketFactory", options.getSocketFactory() instanceof SSLSocketFactory); - } - - /** - * @see DATAMONGO-764 - */ - @Test - public void testMongoSingletonWithSslEnabledAndCustomSslSocketFactory() throws Exception { - - assertTrue(ctx.containsBean("mongoSslWithCustomSslFactory")); - MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&mongoSslWithCustomSslFactory"); - - SSLSocketFactory customSslSocketFactory = ctx.getBean("customSslSocketFactory", SSLSocketFactory.class); - MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); - - assertTrue("socketFactory should be a SSLSocketFactory", options.getSocketFactory() instanceof SSLSocketFactory); - assertSame(customSslSocketFactory, options.getSocketFactory()); + + MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); + assertFalse("By default socketFactory should not be a SSLSocketFactory", + options.getSocketFactory() instanceof SSLSocketFactory); + } + + /** + * @see DATAMONGO-764 + */ + @Test + public void testMongoSingletonWithSslEnabled() throws Exception { + + assertTrue(ctx.containsBean("mongoSsl")); + MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&mongoSsl"); + + MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); + assertTrue("socketFactory should be a SSLSocketFactory", options.getSocketFactory() instanceof SSLSocketFactory); + } + + /** + * @see DATAMONGO-764 + */ + @Test + public void testMongoSingletonWithSslEnabledAndCustomSslSocketFactory() throws Exception { + + assertTrue(ctx.containsBean("mongoSslWithCustomSslFactory")); + MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&mongoSslWithCustomSslFactory"); + + SSLSocketFactory customSslSocketFactory = ctx.getBean("customSslSocketFactory", SSLSocketFactory.class); + MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); + + assertTrue("socketFactory should be a SSLSocketFactory", options.getSocketFactory() instanceof SSLSocketFactory); + assertSame(customSslSocketFactory, options.getSocketFactory()); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java index 2d51ab6f3..0ca28717e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoParserIntegrationTests.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; @@ -44,8 +45,9 @@ public class MongoParserIntegrationTests { @Before public void setUp() { - factory = new DefaultListableBeanFactory(); - reader = new XmlBeanDefinitionReader(factory); + + this.factory = new DefaultListableBeanFactory(); + this.reader = new XmlBeanDefinitionReader(factory); } @Test @@ -68,9 +70,10 @@ public class MongoParserIntegrationTests { reader.loadBeanDefinitions(new ClassPathResource("namespace/mongo-bean.xml")); - GenericApplicationContext context = new GenericApplicationContext(factory); + AbstractApplicationContext context = new GenericApplicationContext(factory); context.refresh(); assertThat(context.getBean("mongo2", Mongo.class), is(notNullValue())); + context.close(); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java index 3c922ea0d..6f6c84665 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JmxServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.mongodb.core; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -22,6 +21,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * Server application than can be run as an app or unit test. * * @author Mark Pollack + * @author Oliver Gierke */ public class JmxServer { @@ -29,8 +29,8 @@ public class JmxServer { new JmxServer().run(); } + @SuppressWarnings("resource") public void run() { new ClassPathXmlApplicationContext(new String[] { "infrastructure.xml", "server-jmx.xml" }); } - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoDbUtilsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoDbUtilsIntegrationTests.java index 47b78c639..6a6beaee3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoDbUtilsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoDbUtilsIntegrationTests.java @@ -32,6 +32,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean; import com.mongodb.DB; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoException; /** @@ -54,7 +55,7 @@ public class MongoDbUtilsIntegrationTests { @BeforeClass public static void setUp() throws Exception { - mongo = new Mongo(); + mongo = new MongoClient(); template = new MongoTemplate(mongo, DATABASE_NAME); // Create sample user diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index f3e1b0338..cd4e89139 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -57,6 +57,8 @@ import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.convert.CustomConversions; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.Index.Duplicates; @@ -119,7 +121,8 @@ public class MongoTemplateTests { mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); mappingContext.initialize(); - MappingMongoConverter mappingConverter = new MappingMongoConverter(factory, mappingContext); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); + MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mappingContext); mappingConverter.setCustomConversions(conversions); mappingConverter.afterPropertiesSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index 0ae20f548..d5e8467d8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -40,6 +40,7 @@ import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.convert.CustomConversions; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator; @@ -76,13 +77,14 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { @Before public void setUp() { - this.mappingContext = new MongoMappingContext(); - this.converter = new MappingMongoConverter(factory, mappingContext); - this.template = new MongoTemplate(factory, converter); - when(factory.getDb()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(Mockito.any(String.class))).thenReturn(collection); + + this.mappingContext = new MongoMappingContext(); + this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext); + this.template = new MongoTemplate(factory, converter); + } @Test(expected = IllegalArgumentException.class) diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java index 6c9d28ae4..acfa990dd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExample.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,23 +17,27 @@ package org.springframework.data.mongodb.core; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.context.support.AbstractApplicationContext; +/** + * @author Jon Brisbin + * @author Oliver Gierke + */ public class PersonExample { - private static final Log log = LogFactory.getLog(PersonExample.class); - @Autowired - private MongoOperations mongoOps; + private static final Logger LOGGER = LoggerFactory.getLogger(PersonExample.class); + + @Autowired private MongoOperations mongoOps; public static void main(String[] args) { - ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersonExampleAppConfig.class); + AbstractApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersonExampleAppConfig.class); PersonExample example = applicationContext.getBean(PersonExample.class); example.doWork(); + applicationContext.close(); } public void doWork() { @@ -51,23 +55,23 @@ public class PersonExample { mongoOps.save(p2); - log.debug("Saved: " + p); + LOGGER.debug("Saved: " + p); p = mongoOps.findById(p.getId(), PersonWithIdPropertyOfTypeString.class); - log.debug("Found: " + p); + LOGGER.debug("Found: " + p); // mongoOps.updateFirst(new Query(where("firstName").is("Sven")), new Update().set("age", 24)); // mongoOps.updateFirst(new Query(where("firstName").is("Sven")), update("age", 24)); p = mongoOps.findById(p.getId(), PersonWithIdPropertyOfTypeString.class); - log.debug("Updated: " + p); + LOGGER.debug("Updated: " + p); List folks = mongoOps.findAll(PersonWithIdPropertyOfTypeString.class); - log.debug("Querying for all people..."); + LOGGER.debug("Querying for all people..."); for (PersonWithIdPropertyOfTypeString element : folks) { - log.debug(element); + LOGGER.debug(element.toString()); } // mongoOps.remove( query(whereId().is(p.getId())), p.getClass()); @@ -76,10 +80,7 @@ public class PersonExample { List people = mongoOps.findAll(PersonWithIdPropertyOfTypeString.class); - // PersonWithIdPropertyOfTypeString p2 = mongoOps.findOne(query(whereId().is(p.getId())), - // PersonWithIdPropertyOfTypeString.class); - - log.debug("Number of people = : " + people.size()); + LOGGER.debug("Number of people = : " + people.size()); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java index 36dfa6c62..28fa3b066 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/PersonExampleAppConfig.java @@ -17,16 +17,16 @@ package org.springframework.data.mongodb.core; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.core.MongoTemplate; import com.mongodb.Mongo; +import com.mongodb.MongoClient; @Configuration public class PersonExampleAppConfig { @Bean public Mongo mongo() throws Exception { - return new Mongo("localhost"); + return new MongoClient("localhost"); } @Bean diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java index 2b64e8bf7..b2c0c844d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/SimpleMongoDbFactoryUnitTests.java @@ -39,8 +39,7 @@ import com.mongodb.MongoURI; @RunWith(MockitoJUnitRunner.class) public class SimpleMongoDbFactoryUnitTests { - @Mock - Mongo mongo; + @Mock Mongo mongo; /** * @see DATADOC-254 @@ -66,6 +65,7 @@ public class SimpleMongoDbFactoryUnitTests { * @throws UnknownHostException */ @Test + @SuppressWarnings("deprecation") public void mongoUriConstructor() throws UnknownHostException { MongoURI mongoURI = new MongoURI("mongodb://myUsername:myPassword@localhost/myDatabase.myCollection"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java index 0701556fa..34ee5dcba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java @@ -10,6 +10,7 @@ import org.springframework.data.mongodb.core.convert.CustomConversions; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import com.mongodb.Mongo; +import com.mongodb.MongoClient; public class TestMongoConfiguration extends AbstractMongoConfiguration { @@ -21,7 +22,7 @@ public class TestMongoConfiguration extends AbstractMongoConfiguration { @Override @Bean public Mongo mongo() throws Exception { - return new Mongo("127.0.0.1", 27017); + return new MongoClient("127.0.0.1", 27017); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDbObjectCallbackUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDbObjectCallbackUnitTests.java index 4f842dcfb..4163e5c51 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDbObjectCallbackUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/UnwrapAndReadDbObjectCallbackUnitTests.java @@ -25,6 +25,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate.UnwrapAndReadDbObjectCallback; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -46,7 +47,8 @@ public class UnwrapAndReadDbObjectCallbackUnitTests { public void setUp() { MongoTemplate template = new MongoTemplate(factory); - MappingMongoConverter converter = new MappingMongoConverter(factory, new MongoMappingContext()); + MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), + new MongoMappingContext()); this.callback = template.new UnwrapAndReadDbObjectCallback(converter, Target.class); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java index 5b19ef5b2..a5260b712 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/SpelExpressionTransformerIntegrationTests.java @@ -18,6 +18,7 @@ package org.springframework.data.mongodb.core.aggregation; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -25,6 +26,8 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -45,12 +48,19 @@ public class SpelExpressionTransformerIntegrationTests { @Rule public ExpectedException exception = ExpectedException.none(); - SpelExpressionTransformer transformer = new SpelExpressionTransformer(); + SpelExpressionTransformer transformer; + DbRefResolver dbRefResolver; + + @Before + public void setUp() { + this.transformer = new SpelExpressionTransformer(); + this.dbRefResolver = new DefaultDbRefResolver(mongoDbFactory); + } @Test public void shouldConvertCompoundExpressionToPropertyPath() { - MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory, new MongoMappingContext()); + MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); TypeBasedAggregationOperationContext ctxt = new TypeBasedAggregationOperationContext(Data.class, new MongoMappingContext(), new QueryMapper(converter)); assertThat(transformer.transform("item.primitiveIntValue", ctxt, new Object[0]).toString(), @@ -63,7 +73,7 @@ public class SpelExpressionTransformerIntegrationTests { exception.expect(MappingException.class); exception.expectMessage("value2"); - MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory, new MongoMappingContext()); + MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, new MongoMappingContext()); TypeBasedAggregationOperationContext ctxt = new TypeBasedAggregationOperationContext(Data.class, new MongoMappingContext(), new QueryMapper(converter)); assertThat(transformer.transform("item.value2", ctxt, new Object[0]).toString(), is("$item.value2")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java index 68c69793b..1047464f1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/TypeBasedAggregationOperationContextUnitTests.java @@ -24,7 +24,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.mapping.model.MappingException; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -41,13 +41,13 @@ public class TypeBasedAggregationOperationContextUnitTests { MappingMongoConverter converter; QueryMapper mapper; - @Mock MongoDbFactory dbFactory; + @Mock DbRefResolver dbRefResolver; @Before public void setUp() { this.context = new MongoMappingContext(); - this.converter = new MappingMongoConverter(dbFactory, context); + this.converter = new MappingMongoConverter(dbRefResolver, context); this.mapper = new QueryMapper(converter); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java index 3e67dd283..e26394f11 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/CustomConvertersUnitTests.java @@ -48,12 +48,9 @@ public class CustomConvertersUnitTests { MappingMongoConverter converter; - @Mock - BarToDBObjectConverter barToDBObjectConverter; - @Mock - DBObjectToBarConverter dbObjectToBarConverter; - @Mock - MongoDbFactory mongoDbFactory; + @Mock BarToDBObjectConverter barToDBObjectConverter; + @Mock DBObjectToBarConverter dbObjectToBarConverter; + @Mock MongoDbFactory mongoDbFactory; MongoMappingContext context; MongoPersistentEntity fooEntity; @@ -73,7 +70,7 @@ public class CustomConvertersUnitTests { context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); context.initialize(); - converter = new MappingMongoConverter(mongoDbFactory, context); + converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context); converter.setCustomConversions(conversions); converter.afterPropertiesSet(); } @@ -121,14 +118,12 @@ public class CustomConvertersUnitTests { } public static class Foo { - @Id - public String id; + @Id public String id; public Bar bar; } public static class Bar { - @Id - public String id; + @Id public String id; public String foo; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java index fa9e77630..5c3ae804e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DataMongo273Tests.java @@ -25,7 +25,6 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; -import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import com.mongodb.BasicDBList; @@ -43,10 +42,10 @@ public class DataMongo273Tests { MappingMongoConverter converter; @Before - public void setupMongoConv() { + public void setupMongoConverter() { MongoMappingContext mappingContext = new MongoMappingContext(); - MongoDbFactory factory = mock(MongoDbFactory.class); + DbRefResolver factory = mock(DbRefResolver.class); converter = new MappingMongoConverter(factory, mappingContext); converter.afterPropertiesSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java new file mode 100644 index 000000000..6d71aff10 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java @@ -0,0 +1,339 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.convert; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; +import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.*; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +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.data.annotation.Id; +import org.springframework.data.annotation.PersistenceConstructor; +import org.springframework.data.mapping.PropertyPath; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoExceptionTranslator; +import org.springframework.data.mongodb.core.convert.MappingMongoConverterUnitTests.Person; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import com.mongodb.DBRef; + +/** + * @author Oliver Gierke + */ +@RunWith(MockitoJUnitRunner.class) +public class DbRefMappingMongoConverterUnitTests { + + MappingMongoConverter converter; + MongoMappingContext mappingContext; + + @Mock MongoDbFactory dbFactory; + + @Before + public void setUp() { + + when(dbFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); + + this.mappingContext = new MongoMappingContext(); + this.converter = new MappingMongoConverter(new DefaultDbRefResolver(dbFactory), mappingContext); + } + + /** + * @see DATAMONGO-347 + */ + @Test + public void createsSimpleDBRefCorrectly() { + + Person person = new Person(); + person.id = "foo"; + + DBRef dbRef = converter.toDBRef(person, null); + assertThat(dbRef.getId(), is((Object) "foo")); + assertThat(dbRef.getRef(), is("person")); + } + + /** + * @see DATAMONGO-657 + */ + @Test + public void convertDocumentWithMapDBRef() { + + MapDBRef mapDBRef = new MapDBRef(); + + MapDBRefVal val = new MapDBRefVal(); + val.id = BigInteger.ONE; + + Map mapVal = new HashMap(); + mapVal.put("test", val); + + mapDBRef.map = mapVal; + + BasicDBObject dbObject = new BasicDBObject(); + converter.write(mapDBRef, dbObject); + + DBObject map = (DBObject) dbObject.get("map"); + + assertThat(map.get("test"), instanceOf(DBRef.class)); + + DBObject mapValDBObject = new BasicDBObject(); + mapValDBObject.put("_id", BigInteger.ONE); + + DBRef dbRef = mock(DBRef.class); + when(dbRef.fetch()).thenReturn(mapValDBObject); + + ((DBObject) dbObject.get("map")).put("test", dbRef); + + MapDBRef read = converter.read(MapDBRef.class, dbObject); + + assertThat(read.map.get("test").id, is(BigInteger.ONE)); + } + + /** + * @see DATAMONGO-347 + */ + @Test + public void createsDBRefWithClientSpecCorrectly() { + + PropertyPath path = PropertyPath.from("person", PersonClient.class); + MongoPersistentProperty property = mappingContext.getPersistentPropertyPath(path).getLeafProperty(); + + Person person = new Person(); + person.id = "foo"; + + DBRef dbRef = converter.toDBRef(person, property); + assertThat(dbRef.getId(), is((Object) "foo")); + assertThat(dbRef.getRef(), is("person")); + } + + /** + * @see DATAMONGO-348 + */ + @Test + public void lazyLoadingProxyForLazyDbRefOnInterface() { + + String id = "42"; + String value = "bubu"; + MappingMongoConverter converterSpy = spy(converter); + doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); + + BasicDBObject dbo = new BasicDBObject(); + ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); + lazyDbRefs.dbRefToInterface = new LinkedList(Arrays.asList(new LazyDbRefTarget("1"))); + converterSpy.write(lazyDbRefs, dbo); + + ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); + + assertProxyIsResolved(result.dbRefToInterface, false); + assertThat(result.dbRefToInterface.get(0).getId(), is(id)); + assertProxyIsResolved(result.dbRefToInterface, true); + assertThat(result.dbRefToInterface.get(0).getValue(), is(value)); + } + + /** + * @see DATAMONGO-348 + */ + @Test + public void lazyLoadingProxyForLazyDbRefOnConcreteCollection() { + + String id = "42"; + String value = "bubu"; + MappingMongoConverter converterSpy = spy(converter); + doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); + + BasicDBObject dbo = new BasicDBObject(); + ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); + lazyDbRefs.dbRefToConcreteCollection = new ArrayList(Arrays.asList(new LazyDbRefTarget(id, value))); + converterSpy.write(lazyDbRefs, dbo); + + ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); + + assertProxyIsResolved(result.dbRefToConcreteCollection, false); + assertThat(result.dbRefToConcreteCollection.get(0).getId(), is(id)); + assertProxyIsResolved(result.dbRefToConcreteCollection, true); + assertThat(result.dbRefToConcreteCollection.get(0).getValue(), is(value)); + } + + /** + * @see DATAMONGO-348 + */ + @Test + public void lazyLoadingProxyForLazyDbRefOnConcreteType() { + + String id = "42"; + String value = "bubu"; + MappingMongoConverter converterSpy = spy(converter); + doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); + + BasicDBObject dbo = new BasicDBObject(); + ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); + lazyDbRefs.dbRefToConcreteType = new LazyDbRefTarget(id, value); + converterSpy.write(lazyDbRefs, dbo); + + ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); + + assertProxyIsResolved(result.dbRefToConcreteType, false); + assertThat(result.dbRefToConcreteType.getId(), is(id)); + assertProxyIsResolved(result.dbRefToConcreteType, true); + assertThat(result.dbRefToConcreteType.getValue(), is(value)); + } + + /** + * @see DATAMONGO-348 + */ + @Test + public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructor() { + + String id = "42"; + String value = "bubu"; + MappingMongoConverter converterSpy = spy(converter); + doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); + + BasicDBObject dbo = new BasicDBObject(); + ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); + lazyDbRefs.dbRefToConcreteTypeWithPersistenceConstructor = new LazyDbRefTargetWithPeristenceConstructor( + (Object) id, (Object) value); + converterSpy.write(lazyDbRefs, dbo); + + ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); + + assertProxyIsResolved(result.dbRefToConcreteTypeWithPersistenceConstructor, false); + assertThat(result.dbRefToConcreteTypeWithPersistenceConstructor.getId(), is(id)); + assertProxyIsResolved(result.dbRefToConcreteTypeWithPersistenceConstructor, true); + assertThat(result.dbRefToConcreteTypeWithPersistenceConstructor.getValue(), is(value)); + } + + /** + * @see DATAMONGO-348 + */ + @Test + public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructorButWithoutDefaultConstructor() { + + String id = "42"; + String value = "bubu"; + MappingMongoConverter converterSpy = spy(converter); + doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); + + BasicDBObject dbo = new BasicDBObject(); + ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); + lazyDbRefs.dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor = new LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor( + (Object) id, (Object) value); + converterSpy.write(lazyDbRefs, dbo); + + ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); + + assertProxyIsResolved(result.dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor, false); + assertThat(result.dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor.getId(), is(id)); + assertProxyIsResolved(result.dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor, true); + assertThat(result.dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor.getValue(), is(value)); + } + + class MapDBRef { + @org.springframework.data.mongodb.core.mapping.DBRef Map map; + } + + class MapDBRefVal { + BigInteger id; + } + + class PersonClient { + @org.springframework.data.mongodb.core.mapping.DBRef Person person; + } + + static class ClassWithLazyDbRefs { + + @Id String id; + @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) List dbRefToInterface; + @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) ArrayList dbRefToConcreteCollection; + @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTarget dbRefToConcreteType; + @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructor dbRefToConcreteTypeWithPersistenceConstructor; + @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor dbRefToConcreteTypeWithPersistenceConstructorWithoutDefaultConstructor; + } + + static class LazyDbRefTarget { + + @Id String id; + String value; + + public LazyDbRefTarget() { + this(null); + } + + public LazyDbRefTarget(String id) { + this(id, null); + } + + public LazyDbRefTarget(String id, String value) { + this.id = id; + this.value = value; + } + + public String getId() { + return id; + } + + public String getValue() { + return value; + } + } + + static class LazyDbRefTargetWithPeristenceConstructor extends LazyDbRefTarget { + + boolean persistenceConstructorCalled; + + public LazyDbRefTargetWithPeristenceConstructor() {} + + @PersistenceConstructor + public LazyDbRefTargetWithPeristenceConstructor(String id, String value) { + super(id, value); + this.persistenceConstructorCalled = true; + } + + public LazyDbRefTargetWithPeristenceConstructor(Object id, Object value) { + super(id.toString(), value.toString()); + } + } + + static class LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor extends LazyDbRefTarget { + + boolean persistenceConstructorCalled; + + @PersistenceConstructor + public LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor(String id, String value) { + super(id, value); + this.persistenceConstructorCalled = true; + } + + public LazyDbRefTargetWithPeristenceConstructorWithoutDefaultConstructor(Object id, Object value) { + super(id.toString(), value.toString()); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java new file mode 100644 index 000000000..2d5b6c690 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/LazyLoadingTestUtils.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.core.convert; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.springframework.aop.framework.Advised; +import org.springframework.cglib.proxy.Factory; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver.LazyLoadingInterceptor; + +/** + * Utility class to test proxy handling for lazy loading. + * + * @author Oliver Gierke + */ +public class LazyLoadingTestUtils { + + /** + * Asserts that the given repository is resolved (expected is {@literal true}) and the value is non-{@literal null} or + * unresolved (expected is {@literal false}) and the value is {@literal null}. + * + * @param target + * @param expected + */ + public static void assertProxyIsResolved(Object target, boolean expected) { + + LazyLoadingInterceptor interceptor = extractInterceptor(target); + assertThat(interceptor.isResolved(), is(expected)); + assertThat(interceptor.getResult(), is(expected ? notNullValue() : nullValue())); + } + + private static LazyLoadingInterceptor extractInterceptor(Object proxy) { + return (LazyLoadingInterceptor) (proxy instanceof Advised ? ((Advised) proxy).getAdvisors()[0].getAdvice() + : ((Factory) proxy).getCallback(0)); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 7719c7b04..3d80c35b5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core.convert; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; -import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.math.BigDecimal; @@ -30,7 +29,6 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -45,28 +43,20 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.aop.Advisor; -import org.springframework.aop.framework.Advised; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.core.convert.converter.Converter; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.annotation.TypeAlias; -import org.springframework.data.mapping.PropertyPath; import org.springframework.data.mapping.model.MappingException; import org.springframework.data.mapping.model.MappingInstantiationException; -import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.DBObjectTestUtils; -import org.springframework.data.mongodb.core.MongoExceptionTranslator; import org.springframework.data.mongodb.core.convert.DBObjectAccessorUnitTests.NestedType; import org.springframework.data.mongodb.core.convert.DBObjectAccessorUnitTests.ProjectingType; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter.LazyLoadingInterceptor; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter.LazyLoadingProxy; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; -import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.PersonPojoStringId; import org.springframework.test.util.ReflectionTestUtils; @@ -88,19 +78,17 @@ public class MappingMongoConverterUnitTests { MappingMongoConverter converter; MongoMappingContext mappingContext; - @Mock MongoDbFactory factory; @Mock ApplicationContext context; + @Mock DbRefResolver resolver; @Before public void setUp() { - when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); - mappingContext = new MongoMappingContext(); mappingContext.setApplicationContext(context); mappingContext.afterPropertiesSet(); - converter = new MappingMongoConverter(factory, mappingContext); + converter = new MappingMongoConverter(resolver, mappingContext); converter.afterPropertiesSet(); } @@ -122,7 +110,7 @@ public class MappingMongoConverterUnitTests { @Test public void convertsJodaTimeTypesCorrectly() { - converter = new MappingMongoConverter(factory, mappingContext); + converter = new MappingMongoConverter(resolver, mappingContext); converter.afterPropertiesSet(); Person person = new Person(); @@ -140,7 +128,7 @@ public class MappingMongoConverterUnitTests { @Test public void convertsCustomTypeOnConvertToMongoType() { - converter = new MappingMongoConverter(factory, mappingContext); + converter = new MappingMongoConverter(resolver, mappingContext); converter.afterPropertiesSet(); LocalDate date = new LocalDate(); @@ -1055,37 +1043,6 @@ public class MappingMongoConverterUnitTests { assertSyntheticFieldValueOf(outer.inner, outer); } - /** - * @see DATAMONGO-347 - */ - @Test - public void createsSimpleDBRefCorrectly() { - - Person person = new Person(); - person.id = "foo"; - - DBRef dbRef = converter.toDBRef(person, null); - assertThat(dbRef.getId(), is((Object) "foo")); - assertThat(dbRef.getRef(), is("person")); - } - - /** - * @see DATAMONGO-347 - */ - @Test - public void createsDBRefWithClientSpecCorrectly() { - - PropertyPath path = PropertyPath.from("person", PersonClient.class); - MongoPersistentProperty property = mappingContext.getPersistentPropertyPath(path).getLeafProperty(); - - Person person = new Person(); - person.id = "foo"; - - DBRef dbRef = converter.toDBRef(person, property); - assertThat(dbRef.getId(), is((Object) "foo")); - assertThat(dbRef.getRef(), is("person")); - } - /** * @see DATAMONGO-458 */ @@ -1330,42 +1287,6 @@ public class MappingMongoConverterUnitTests { converter.read(ObjectContainer.class, input); } - /** - * @see DATAMONGO-657 - */ - @Test - public void convertDocumentWithMapDBRef() { - - MapDBRef mapDBRef = new MapDBRef(); - - MapDBRefVal val = new MapDBRefVal(); - val.id = BigInteger.ONE; - - Map mapVal = new HashMap(); - mapVal.put("test", val); - - mapDBRef.map = mapVal; - - BasicDBObject dbObject = new BasicDBObject(); - converter.write(mapDBRef, dbObject); - - DBObject map = (DBObject) dbObject.get("map"); - - assertThat(map.get("test"), instanceOf(DBRef.class)); - - DBObject mapValDBObject = new BasicDBObject(); - mapValDBObject.put("_id", BigInteger.ONE); - - DBRef dbRef = mock(DBRef.class); - when(dbRef.fetch()).thenReturn(mapValDBObject); - - ((DBObject) dbObject.get("map")).put("test", dbRef); - - MapDBRef read = converter.read(MapDBRef.class, dbObject); - - assertThat(read.map.get("test").id, is(BigInteger.ONE)); - } - /** * @see DATAMONGO-724 */ @@ -1405,7 +1326,7 @@ public class MappingMongoConverterUnitTests { context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); context.afterPropertiesSet(); - MappingMongoConverter mongoConverter = new MappingMongoConverter(factory, context); + MappingMongoConverter mongoConverter = new MappingMongoConverter(resolver, context); mongoConverter.setCustomConversions(conversions); mongoConverter.afterPropertiesSet(); @@ -1460,130 +1381,6 @@ public class MappingMongoConverterUnitTests { assertThat(aValue.get("c"), is((Object) "C")); } - /** - * @see DATAMONGO-348 - */ - @Test - public void lazyLoadingProxyForLazyDbRefOnInterface() { - - String id = "42"; - String value = "bubu"; - MappingMongoConverter converterSpy = spy(converter); - doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); - - BasicDBObject dbo = new BasicDBObject(); - ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); - lazyDbRefs.dbRefToInterface = new LinkedList(Arrays.asList(new LazyDbRefTarget("1"))); - converterSpy.write(lazyDbRefs, dbo); - - ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); - - assertTrue(result.dbRefToInterface instanceof LazyLoadingProxy); - - LazyLoadingInterceptor interceptor = extractInterceptor(result.dbRefToInterface); - assertThat(interceptor.isResolved(), is(false)); - assertThat(result.dbRefToInterface.get(0).getId(), is(id)); - assertThat(interceptor.isResolved(), is(true)); - assertThat(result.dbRefToInterface.get(0).getValue(), is(value)); - } - - /** - * @see DATAMONGO-348 - */ - @Test - public void lazyLoadingProxyForLazyDbRefOnConcreteCollection() { - - String id = "42"; - String value = "bubu"; - MappingMongoConverter converterSpy = spy(converter); - doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); - - BasicDBObject dbo = new BasicDBObject(); - ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); - lazyDbRefs.dbRefToConcreteCollection = new ArrayList(Arrays.asList(new LazyDbRefTarget(id, value))); - converterSpy.write(lazyDbRefs, dbo); - - ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); - - assertTrue(result.dbRefToConcreteCollection instanceof LazyLoadingProxy); - - LazyLoadingInterceptor interceptor = extractInterceptor(result.dbRefToConcreteCollection); - assertThat(interceptor.isResolved(), is(false)); - assertThat(result.dbRefToConcreteCollection.get(0).getId(), is(id)); - assertThat(interceptor.isResolved(), is(true)); - assertThat(result.dbRefToConcreteCollection.get(0).getValue(), is(value)); - } - - /** - * @see DATAMONGO-348 - */ - @Test - public void lazyLoadingProxyForLazyDbRefOnConcreteType() { - - String id = "42"; - String value = "bubu"; - MappingMongoConverter converterSpy = spy(converter); - doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); - - BasicDBObject dbo = new BasicDBObject(); - ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); - lazyDbRefs.dbRefToConcreteType = new LazyDbRefTarget(id, value); - converterSpy.write(lazyDbRefs, dbo); - - ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); - - assertTrue(result.dbRefToConcreteType instanceof LazyLoadingProxy); - - LazyLoadingInterceptor interceptor = extractInterceptor(result.dbRefToConcreteType); - assertThat(interceptor.isResolved(), is(false)); - assertThat(result.dbRefToConcreteType.getId(), is(id)); - assertThat(interceptor.isResolved(), is(true)); - assertThat(result.dbRefToConcreteType.getValue(), is(value)); - } - - /** - * @see DATAMONGO-348 - */ - @Test - public void lazyLoadingProxyForLazyDbRefOnConcreteTypeWithPersistenceConstructor() { - - String id = "42"; - String value = "bubu"; - MappingMongoConverter converterSpy = spy(converter); - doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any()); - - BasicDBObject dbo = new BasicDBObject(); - ClassWithLazyDbRefs lazyDbRefs = new ClassWithLazyDbRefs(); - lazyDbRefs.dbRefToConcreteTypeWithPersistenceConstructor = new LazyDbRefTargetWithPeristenceConstructor( - (Object) id, (Object) value); - converterSpy.write(lazyDbRefs, dbo); - - ClassWithLazyDbRefs result = converterSpy.read(ClassWithLazyDbRefs.class, dbo); - - assertTrue(result.dbRefToConcreteTypeWithPersistenceConstructor instanceof LazyLoadingProxy); - - LazyLoadingInterceptor interceptor = extractInterceptor(result.dbRefToConcreteTypeWithPersistenceConstructor); - assertThat(interceptor.isResolved(), is(false)); - assertThat(result.dbRefToConcreteTypeWithPersistenceConstructor.getId(), is(id)); - assertThat(interceptor.isResolved(), is(true)); - assertThat(result.dbRefToConcreteTypeWithPersistenceConstructor.getValue(), is(value)); - assertThat(result.dbRefToConcreteTypeWithPersistenceConstructor.isPersistanceConstructorCalled(), is(true)); - } - - private LazyLoadingInterceptor extractInterceptor(Object proxy) { - return (LazyLoadingInterceptor) ((Advisor) ((Advised) proxy).getAdvisors()[0]).getAdvice(); - } - - @Document - class MapDBRef { - @org.springframework.data.mongodb.core.mapping.DBRef Map map; - } - - @Document - class MapDBRefVal { - BigInteger id; - } - static class GenericType { T content; } @@ -1727,11 +1524,6 @@ public class MappingMongoConverterUnitTests { Inner inner; } - static class PersonClient { - - @org.springframework.data.mongodb.core.mapping.DBRef Person person; - } - static class DBRefWrapper { DBRef ref; @@ -1801,72 +1593,4 @@ public class MappingMongoConverterUnitTests { return m_property; } } - - static class ClassWithLazyDbRefs { - @Id String id; - - @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) List dbRefToInterface; - - @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) ArrayList dbRefToConcreteCollection; - - @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTarget dbRefToConcreteType; - - @org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) LazyDbRefTargetWithPeristenceConstructor dbRefToConcreteTypeWithPersistenceConstructor; - } - - static class LazyDbRefTarget { - @Id String id; - - String value; - - public LazyDbRefTarget() { - this(null); - } - - public LazyDbRefTarget(String id) { - this(id, null); - } - - public LazyDbRefTarget(String id, String value) { - this.id = id; - this.value = value; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - - static class LazyDbRefTargetWithPeristenceConstructor extends LazyDbRefTarget { - - boolean persistanceConstructorCalled; - - public LazyDbRefTargetWithPeristenceConstructor() {} - - @PersistenceConstructor - public LazyDbRefTargetWithPeristenceConstructor(String id, String value) { - super(id, value); - this.persistanceConstructorCalled = true; - } - - public LazyDbRefTargetWithPeristenceConstructor(Object id, Object value) { - super(id.toString(), value.toString()); - } - - public boolean isPersistanceConstructorCalled() { - return persistanceConstructorCalled; - } - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index a7c07cc90..34cd8716d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -69,12 +69,12 @@ public class QueryMapperUnitTests { @Before public void setUp() { - context = new MongoMappingContext(); + this.context = new MongoMappingContext(); - converter = new MappingMongoConverter(factory, context); - converter.afterPropertiesSet(); + this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); + this.converter.afterPropertiesSet(); - mapper = new QueryMapper(converter); + this.mapper = new QueryMapper(converter); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index 68d794059..66965d13f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -46,8 +46,9 @@ public class UpdateMapperUnitTests { @Before public void setUp() { - context = new MongoMappingContext(); - converter = new MappingMongoConverter(factory, context); + + this.context = new MongoMappingContext(); + this.converter = new MappingMongoConverter(new DefaultDbRefResolver(factory), context); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialAppConfig.java deleted file mode 100644 index 020cd335d..000000000 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialAppConfig.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-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.mongodb.core.geo; - -import com.mongodb.Mongo; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.mongodb.config.AbstractMongoConfiguration; -import org.springframework.data.mongodb.core.mapping.event.LoggingEventListener; - -@Configuration -public class GeoSpatialAppConfig extends AbstractMongoConfiguration { - - @Override - public String getDatabaseName() { - return "database"; - } - - @Override - @Bean - public Mongo mongo() throws Exception { - return new Mongo("127.0.0.1"); - } - - @Bean - public LoggingEventListener mappingEventsListener() { - return new LoggingEventListener(); - } - - @Override - public String getMappingBasePackage() { - return "org.springframework.data.mongodb.core.core"; - } - -} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java index da7e1ad3a..1f929a9a3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoSpatialTests.java @@ -21,19 +21,17 @@ import static org.junit.Assert.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; -import java.net.UnknownHostException; import java.util.Collection; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionCallback; import org.springframework.data.mongodb.core.IndexOperations; import org.springframework.data.mongodb.core.MongoTemplate; @@ -43,14 +41,11 @@ import org.springframework.data.mongodb.core.index.IndexField; import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.monitor.ServerInfo; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; -import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; -import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.WriteConcern; @@ -60,41 +55,22 @@ import com.mongodb.WriteConcern; * @author Mark Pollack * @author Oliver Gierke */ -public class GeoSpatialTests { +public class GeoSpatialTests extends AbstractIntegrationTests { private static final Log LOGGER = LogFactory.getLog(GeoSpatialTests.class); - private final String[] collectionsToDrop = new String[] { "newyork", "Person" }; - ApplicationContext applicationContext; - MongoTemplate template; - ServerInfo serverInfo; + @Autowired MongoTemplate template; - ExpressionParser parser; + ExpressionParser parser = new SpelExpressionParser(); @Before public void setUp() throws Exception { - cleanDb(); - applicationContext = new AnnotationConfigApplicationContext(GeoSpatialAppConfig.class); - template = applicationContext.getBean(MongoTemplate.class); + template.setWriteConcern(WriteConcern.FSYNC_SAFE); template.indexOps(Venue.class).ensureIndex(new GeospatialIndex("location")); + indexCreated(); addVenues(); - parser = new SpelExpressionParser(); - } - - @After - public void cleanUp() throws Exception { - cleanDb(); - } - - private void cleanDb() throws UnknownHostException { - Mongo mongo = new Mongo(); - serverInfo = new ServerInfo(mongo); - DB db = mongo.getDB("database"); - for (String coll : collectionsToDrop) { - db.getCollection(coll).drop(); - } } private void addVenues() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java index 17c2ba96b..29a2cadc9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GenericMappingTests.java @@ -26,7 +26,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -44,16 +44,16 @@ public class GenericMappingTests { MongoMappingContext context; MongoConverter converter; - @Mock - MongoDbFactory factory; + @Mock DbRefResolver resolver; @Before public void setUp() throws Exception { + context = new MongoMappingContext(); context.setInitialEntitySet(Collections.singleton(StringWrapper.class)); context.initialize(); - converter = new MappingMongoConverter(factory, context); + converter = new MappingMongoConverter(resolver, context); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java index 6a01616ad..3c49752f6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java @@ -1,10 +1,27 @@ +/* + * Copyright 2011-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.data.mongodb.core.mapping; -import com.mongodb.Mongo; import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.core.mapping.event.LoggingEventListener; +import com.mongodb.Mongo; +import com.mongodb.MongoClient; + public class GeoIndexedAppConfig extends AbstractMongoConfiguration { public static String GEO_DB = "database"; @@ -18,7 +35,7 @@ public class GeoIndexedAppConfig extends AbstractMongoConfiguration { @Override @Bean public Mongo mongo() throws Exception { - return new Mongo("127.0.0.1"); + return new MongoClient("127.0.0.1"); } @Override diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java index 9f2c10d90..1b6ed4ff3 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedTests.java @@ -1,11 +1,11 @@ /* - * Copyright (c) 2011 by the original author(s). + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.mongodb.core.mapping; import static org.junit.Assert.*; @@ -24,36 +23,39 @@ import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.dao.DataAccessException; import org.springframework.data.mongodb.core.CollectionCallback; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoException; /** - * @author Jon Brisbin + * @author Jon Brisbin + * @author Oliver Gierke */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = GeoIndexedAppConfig.class) public class GeoIndexedTests { private final String[] collectionsToDrop = new String[] { GeoIndexedAppConfig.GEO_COLLECTION, "Person" }; - ApplicationContext applicationContext; - MongoTemplate template; - MongoMappingContext mappingContext; + @Autowired ApplicationContext applicationContext; + @Autowired MongoTemplate template; + @Autowired MongoMappingContext mappingContext; @Before public void setUp() throws Exception { cleanDb(); - applicationContext = new AnnotationConfigApplicationContext(GeoIndexedAppConfig.class); - template = applicationContext.getBean(MongoTemplate.class); - mappingContext = applicationContext.getBean(MongoMappingContext.class); } @After @@ -62,8 +64,10 @@ public class GeoIndexedTests { } private void cleanDb() throws UnknownHostException { - Mongo mongo = new Mongo(); + + Mongo mongo = new MongoClient(); DB db = mongo.getDB(GeoIndexedAppConfig.GEO_DB); + for (String coll : collectionsToDrop) { db.getCollection(coll).drop(); } @@ -88,5 +92,4 @@ public class GeoIndexedTests { assertTrue(hasIndex); } - } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java index c7f6f0cc0..bfd453517 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java @@ -27,71 +27,32 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.bson.types.ObjectId; -import org.junit.Before; import org.junit.Test; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; +import org.springframework.dao.DuplicateKeyException; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mongodb.MongoCollectionUtils; +import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionCallback; -import org.springframework.data.mongodb.core.MongoDbUtils; -import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; -import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; -import com.mongodb.Mongo; import com.mongodb.MongoException; /** * @author Jon Brisbin * @author Oliver Gierke */ -public class MappingTests { - - private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class); - private final String[] collectionsToDrop = new String[] { - MongoCollectionUtils.getPreferredCollectionName(Person.class), - MongoCollectionUtils.getPreferredCollectionName(PersonMapProperty.class), - MongoCollectionUtils.getPreferredCollectionName(PersonWithObjectId.class), - MongoCollectionUtils.getPreferredCollectionName(PersonPojoIntId.class), - MongoCollectionUtils.getPreferredCollectionName(PersonPojoLongId.class), - MongoCollectionUtils.getPreferredCollectionName(PersonPojoStringId.class), - MongoCollectionUtils.getPreferredCollectionName(PersonCustomIdName.class), - MongoCollectionUtils.getPreferredCollectionName(PersonMultiDimArrays.class), - MongoCollectionUtils.getPreferredCollectionName(PersonMultiCollection.class), - MongoCollectionUtils.getPreferredCollectionName(PersonWithDbRef.class), - MongoCollectionUtils.getPreferredCollectionName(PersonWithLongDBRef.class), - MongoCollectionUtils.getPreferredCollectionName(PersonNullProperties.class), - MongoCollectionUtils.getPreferredCollectionName(Account.class), - MongoCollectionUtils.getPreferredCollectionName(PrimitiveId.class), "foobar", "geolocation", "person1", - "person2", "account" }; - - ApplicationContext applicationContext; - Mongo mongo; - MongoTemplate template; - MappingContext, MongoPersistentProperty> mappingContext; - - @Before - public void setUp() throws Exception { - mongo = new Mongo(); - DB db = mongo.getDB("database"); - for (String coll : collectionsToDrop) { - db.getCollection(coll).drop(); - } - applicationContext = new ClassPathXmlApplicationContext("/mapping.xml"); - template = applicationContext.getBean(MongoTemplate.class); - mappingContext = template.getConverter().getMappingContext(); - } +public class MappingTests extends AbstractIntegrationTests { + + @Autowired MongoOperations template; @Test public void testGeneratedId() { @@ -104,11 +65,8 @@ public class MappingTests { @Test public void testPersonPojo() throws Exception { - LOGGER.info("about to create new personpojo"); PersonWithObjectId p = new PersonWithObjectId(12345, "Person", "Pojo"); - LOGGER.info("about to insert"); template.insert(p); - LOGGER.info("done inserting"); assertNotNull(p.getId()); List result = template.find(new Query(Criteria.where("ssn").is(12345)), @@ -203,9 +161,10 @@ public class MappingTests { assertThat(result.get(0).getAccounts(), notNullValue()); } - @Test + @Test(expected = DuplicateKeyException.class) @SuppressWarnings({ "unchecked", "rawtypes" }) public void testUniqueIndex() { + Address addr = new Address(); addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" }); addr.setCity("Anytown"); @@ -215,13 +174,7 @@ public class MappingTests { Person p1 = new Person(1234567890, "John", "Doe", 37, addr); Person p2 = new Person(1234567890, "Jane", "Doe", 38, addr); - List persons = new ArrayList(); - persons.add(p1); - persons.add(p2); - template.insert(persons, MongoCollectionUtils.getPreferredCollectionName(Person.class)); - - List result = template.find(new Query(Criteria.where("ssn").is(1234567890)), Person.class); - assertThat(result.size(), is(1)); + template.insertAll(Arrays.asList(p1, p2)); } @Test @@ -514,23 +467,19 @@ public class MappingTests { static class Container { - @Id - final String id; + @Id final String id; public Container() { id = new ObjectId().toString(); } - @DBRef - Item item; - @DBRef - List items; + @DBRef Item item; + @DBRef List items; } static class Item { - @Id - final String id; + @Id final String id; public Item() { this.id = new ObjectId().toString(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java index 3fec0e988..fcba44928 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTests.java @@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import org.junit.Test; +import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.mongodb.core.mapping.Account; import org.springframework.data.mongodb.repository.Contact; @@ -47,7 +48,7 @@ public class AbstractMongoEventListenerUnitTests { @Test public void dropsEventIfNotForCorrectDomainType() { - ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); + AbstractApplicationContext context = new ClassPathXmlApplicationContext(); context.refresh(); SamplePersonEventListener listener = new SamplePersonEventListener(); @@ -59,6 +60,8 @@ public class AbstractMongoEventListenerUnitTests { listener.invokedOnBeforeConvert = false; context.publishEvent(new BeforeConvertEvent("Test")); assertThat(listener.invokedOnBeforeConvert, is(false)); + + context.close(); } /** diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java index ca4b327f6..a7f163e6b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.mongodb.core.mapping.event; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import java.net.UnknownHostException; @@ -31,6 +31,7 @@ import org.springframework.data.mongodb.core.mapping.PersonPojoStringId; import com.mongodb.DB; import com.mongodb.DBObject; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.WriteConcern; /** @@ -59,7 +60,7 @@ public class ApplicationContextEventTests { } private void cleanDb() throws UnknownHostException { - Mongo mongo = new Mongo(); + Mongo mongo = new MongoClient(); DB db = mongo.getDB("database"); for (String coll : collectionsToDrop) { db.getCollection(coll).drop(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java index 5d4ac5dba..b990c23cd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/ApplicationContextEventTestsAppConfig.java @@ -20,6 +20,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import com.mongodb.Mongo; +import com.mongodb.MongoClient; @Configuration public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfiguration { @@ -32,7 +33,7 @@ public class ApplicationContextEventTestsAppConfig extends AbstractMongoConfigur @Override @Bean public Mongo mongo() throws Exception { - return new Mongo("127.0.0.1"); + return new MongoClient("127.0.0.1"); } @Bean diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java index 1184004ca..5c4ece731 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java @@ -30,6 +30,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.test.context.ContextConfiguration; @@ -45,7 +47,6 @@ import com.mongodb.Mongo; public class GroupByTests { @Autowired MongoDbFactory factory; - @Autowired ApplicationContext applicationContext; MongoTemplate mongoTemplate; @@ -58,11 +59,12 @@ public class GroupByTests { mappingContext.setInitialEntitySet(new HashSet>(Arrays.asList(XObject.class))); mappingContext.initialize(); - MappingMongoConverter mappingConverter = new MappingMongoConverter(factory, mappingContext); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); + MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mappingContext); mappingConverter.afterPropertiesSet(); + this.mongoTemplate = new MongoTemplate(factory, mappingConverter); mongoTemplate.setApplicationContext(applicationContext); - } @Before diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java index 2c67d4460..88b80d7a7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/MapReduceTests.java @@ -34,6 +34,8 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.Query; @@ -56,10 +58,8 @@ public class MapReduceTests { private String mapFunction = "function(){ for ( var i=0; i>(Arrays.asList(ValueObject.class))); mappingContext.initialize(); - MappingMongoConverter mappingConverter = new MappingMongoConverter(factory, mappingContext); + DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); + MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mappingContext); mappingConverter.afterPropertiesSet(); this.mongoTemplate = new MongoTemplate(factory, mappingConverter); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java index 96d540c5b..d130cbbaf 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/performance/PerformanceTests.java @@ -39,6 +39,7 @@ import org.springframework.core.Constants; import org.springframework.data.annotation.PersistenceConstructor; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -56,6 +57,7 @@ import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.WriteConcern; /** @@ -83,7 +85,7 @@ public class PerformanceTests { @Before public void setUp() throws Exception { - this.mongo = new Mongo(); + this.mongo = new MongoClient(); SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(this.mongo, DATABASE_NAME); @@ -91,7 +93,7 @@ public class PerformanceTests { context.setInitialEntitySet(Collections.singleton(Person.class)); context.afterPropertiesSet(); - this.converter = new MappingMongoConverter(mongoDbFactory, context); + this.converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context); this.operations = new MongoTemplate(new SimpleMongoDbFactory(this.mongo, DATABASE_NAME), converter); MongoRepositoryFactoryBean factory = new MongoRepositoryFactoryBean(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java index 1d2d1a005..5bba542d8 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryLazyLoadingIntegrationTests.java @@ -17,6 +17,7 @@ package org.springframework.data.mongodb.repository; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils.*; import java.util.ArrayList; import java.util.Arrays; @@ -25,11 +26,8 @@ import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.aop.Advisor; -import org.springframework.aop.framework.Advised; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter.LazyLoadingInterceptor; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -37,13 +35,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * Integration test for {@link PersonRepository} for lazy loading support. * * @author Thomas Darimont + * @author Oliver Gierke */ @ContextConfiguration(locations = "PersonRepositoryIntegrationTests-context.xml") @RunWith(SpringJUnit4ClassRunner.class) public class PersonRepositoryLazyLoadingIntegrationTests { @Autowired PersonRepository repository; - @Autowired MongoOperations operations; @Before @@ -71,14 +69,11 @@ public class PersonRepositoryLazyLoadingIntegrationTests { Person oliver = repository.findOne(person.id); List fans = oliver.getFans(); - LazyLoadingInterceptor interceptor = extractInterceptor(fans); - assertThat(interceptor.getResult(), is(nullValue())); - assertThat(interceptor.isResolved(), is(false)); + assertProxyIsResolved(fans, false); User user = fans.get(0); - assertThat(interceptor.getResult(), is(notNullValue())); - assertThat(interceptor.isResolved(), is(true)); + assertProxyIsResolved(fans, true); assertThat(user.getUsername(), is(thomas.getUsername())); } @@ -100,19 +95,14 @@ public class PersonRepositoryLazyLoadingIntegrationTests { Person oliver = repository.findOne(person.id); List realFans = oliver.getRealFans(); - LazyLoadingInterceptor interceptor = extractInterceptor(realFans); - - assertThat(interceptor.getResult(), is(nullValue())); - assertThat(interceptor.isResolved(), is(false)); + assertProxyIsResolved(realFans, false); User realFan = realFans.get(0); - assertThat(interceptor.getResult(), is(notNullValue())); - assertThat(interceptor.isResolved(), is(true)); + assertProxyIsResolved(realFans, true); assertThat(realFan.getUsername(), is(thomas.getUsername())); realFans = oliver.getRealFans(); - assertThat(interceptor.getResult(), is(notNullValue())); - assertThat(interceptor.isResolved(), is(true)); + assertProxyIsResolved(realFans, true); realFan = realFans.get(0); assertThat(realFan.getUsername(), is(thomas.getUsername())); @@ -136,16 +126,10 @@ public class PersonRepositoryLazyLoadingIntegrationTests { Person oliver = repository.findOne(person.id); User coworker = oliver.getCoworker(); - LazyLoadingInterceptor interceptor = extractInterceptor(coworker); - assertThat(interceptor.getResult(), is(nullValue())); - assertThat(interceptor.isResolved(), is(false)); + assertProxyIsResolved(coworker, false); assertThat(coworker.getUsername(), is(thomas.getUsername())); - assertThat(interceptor.isResolved(), is(true)); + assertProxyIsResolved(coworker, true); assertThat(coworker.getUsername(), is(thomas.getUsername())); } - - private LazyLoadingInterceptor extractInterceptor(Object proxy) { - return (LazyLoadingInterceptor) ((Advisor) ((Advised) proxy).getAdvisors()[0]).getAdvice(); - } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java index 805e02729..ddc1bcbe1 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/cdi/MongoTemplateProducer.java @@ -25,7 +25,7 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; -import com.mongodb.Mongo; +import com.mongodb.MongoClient; import com.mongodb.MongoException; /** @@ -39,7 +39,7 @@ class MongoTemplateProducer { @ApplicationScoped public MongoOperations createMongoTemplate() throws UnknownHostException, MongoException { - MongoDbFactory factory = new SimpleMongoDbFactory(new Mongo(), "database"); + MongoDbFactory factory = new SimpleMongoDbFactory(new MongoClient(), "database"); return new MongoTemplate(factory); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java index 26989e144..abc00e94e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java @@ -27,7 +27,7 @@ import org.springframework.data.mongodb.repository.PersonRepository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.mongodb.Mongo; +import com.mongodb.MongoClient; /** * Integration tests for {@link MongoRepositoriesRegistrar}. @@ -44,12 +44,11 @@ public class MongoRepositoriesRegistrarIntegrationTests { @Bean public MongoOperations mongoTemplate() throws Exception { - return new MongoTemplate(new SimpleMongoDbFactory(new Mongo(), "database")); + return new MongoTemplate(new SimpleMongoDbFactory(new MongoClient(), "database")); } } - @Autowired - PersonRepository personRepository; + @Autowired PersonRepository personRepository; @Test public void testConfiguration() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java index 10f40c2d2..36f66ef3a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessorUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.convert.DbRefResolver; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -45,28 +47,35 @@ import com.mongodb.BasicDBList; @RunWith(MockitoJUnitRunner.class) public class ConvertingParameterAccessorUnitTests { - @Mock - MongoDbFactory factory; - @Mock - MongoParameterAccessor accessor; + @Mock MongoDbFactory factory; + @Mock MongoParameterAccessor accessor; MongoMappingContext context; MappingMongoConverter converter; + DbRefResolver resolver; @Before public void setUp() { - context = new MongoMappingContext(); - converter = new MappingMongoConverter(factory, context); + + this.context = new MongoMappingContext(); + this.resolver = new DefaultDbRefResolver(factory); + this.converter = new MappingMongoConverter(resolver, context); + } + + @SuppressWarnings("deprecation") + @Test(expected = IllegalArgumentException.class) + public void rejectsNullMongoDbFactory() { + new MappingMongoConverter((MongoDbFactory) null, context); } @Test(expected = IllegalArgumentException.class) - public void rejectsNullWriter() { - new MappingMongoConverter(null, context); + public void rejectsNullDbRefResolver() { + new MappingMongoConverter((DbRefResolver) null, context); } @Test(expected = IllegalArgumentException.class) public void rejectsNullContext() { - new MappingMongoConverter(factory, null); + new MappingMongoConverter(resolver, null); } @Test @@ -136,8 +145,7 @@ public class ConvertingParameterAccessorUnitTests { static class Entity { - @DBRef - Property property; + @DBRef Property property; } static class Property { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java index e23215a66..51fafd902 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/StringBasedMongoQueryUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,8 +26,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; @@ -49,19 +49,18 @@ import com.mongodb.DBObject; @RunWith(MockitoJUnitRunner.class) public class StringBasedMongoQueryUnitTests { - @Mock - MongoOperations operations; - @Mock - RepositoryMetadata metadata; - @Mock - MongoDbFactory factory; + @Mock MongoOperations operations; + @Mock RepositoryMetadata metadata; + @Mock DbRefResolver factory; MongoConverter converter; @Before public void setUp() { - converter = new MappingMongoConverter(factory, new MongoMappingContext()); + when(operations.getConverter()).thenReturn(converter); + + this.converter = new MappingMongoConverter(factory, new MongoMappingContext()); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java index fb7622a04..8a74b8374 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SpringDataMongodbSerializerUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.convert.DbRefResolver; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.data.mongodb.core.mapping.Field; @@ -47,15 +47,17 @@ import com.mysema.query.types.path.StringPath; @RunWith(MockitoJUnitRunner.class) public class SpringDataMongodbSerializerUnitTests { - @Mock MongoDbFactory dbFactory; + @Mock DbRefResolver dbFactory; MongoConverter converter; SpringDataMongodbSerializer serializer; @Before public void setUp() { + MongoMappingContext context = new MongoMappingContext(); - converter = new MappingMongoConverter(dbFactory, context); - serializer = new SpringDataMongodbSerializer(converter); + + this.converter = new MappingMongoConverter(dbFactory, context); + this.serializer = new SpringDataMongodbSerializer(converter); } @Test diff --git a/spring-data-mongodb/src/test/resources/mapping.xml b/spring-data-mongodb/src/test/resources/mapping.xml deleted file mode 100644 index 42c4c6799..000000000 --- a/spring-data-mongodb/src/test/resources/mapping.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/spring-data-mongodb/template.mf b/spring-data-mongodb/template.mf index 054079017..5893f2718 100644 --- a/spring-data-mongodb/template.mf +++ b/spring-data-mongodb/template.mf @@ -17,6 +17,7 @@ Import-Template: javax.validation.*;version="${validation:[=.=.=.=,+1.0.0)}";resolution:=optional, org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional, org.bson.*;version="0", + org.objenesis.*;version="${objenesis:[=.=.=, +1.0.0)}";resolution:=optional, org.slf4j.*;version="${slf4j:[=.=.=,+1.0.0)}", org.springframework.*;version="${spring:[=.=.=.=,+1.0.0)}", org.springframework.data.*;version="${springdata.commons:[=.=.=.=,+1.0.0)}",