DATAMONGO-1874 - @Document's collection attribute now supports EvaluationContextExtensions.

We now use the API newly introduced with DATACMNS-1260 to expose EvaluationContextExtensions to the SpEL evaluation in case the collection attribute of @Document uses SpEL.

Related tickets: DATACMNS-1260.
This commit is contained in:
Oliver Gierke
2018-02-15 10:43:13 +01:00
parent 5a24e04226
commit 9bb8211ed7
7 changed files with 69 additions and 47 deletions

View File

@@ -21,11 +21,6 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
@@ -38,7 +33,6 @@ import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -55,7 +49,7 @@ import org.springframework.util.StringUtils;
* @author Mark Paluch
*/
public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty>
implements MongoPersistentEntity<T>, ApplicationContextAware {
implements MongoPersistentEntity<T> {
private static final String AMBIGUOUS_FIELD_MAPPING = "Ambiguous field mapping detected! Both %s and %s map to the same field name %s! Disambiguate using @Field annotation!";
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
@@ -63,7 +57,6 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
private final String collection;
private final String language;
private final StandardEvaluationContext context;
private final @Nullable Expression expression;
/**
@@ -79,8 +72,6 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
Class<?> rawType = typeInformation.getType();
String fallback = MongoCollectionUtils.getPreferredCollectionName(rawType);
this.context = new StandardEvaluationContext();
if (this.isAnnotationPresent(Document.class)) {
Document document = this.getRequiredAnnotation(Document.class);
@@ -95,23 +86,15 @@ public class BasicMongoPersistentEntity<T> extends BasicPersistentEntity<T, Mong
}
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context.addPropertyAccessor(new BeanFactoryAccessor());
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
context.setRootObject(applicationContext);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentEntity#getCollection()
*/
public String getCollection() {
return expression == null ? collection : expression.getValue(context, String.class);
return expression == null //
? collection //
: expression.getValue(getEvaluationContext(null), String.class);
}
/*

View File

@@ -87,14 +87,7 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
*/
@Override
protected <T> BasicMongoPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
BasicMongoPersistentEntity<T> entity = new BasicMongoPersistentEntity<T>(typeInformation);
if (context != null) {
entity.setApplicationContext(context);
}
return entity;
return new BasicMongoPersistentEntity<T>(typeInformation);
}
/*
@@ -103,6 +96,9 @@ public class MongoMappingContext extends AbstractMappingContext<BasicMongoPersis
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
super.setApplicationContext(applicationContext);
this.context = applicationContext;
}
}

View File

@@ -69,7 +69,7 @@ public class ReactiveStringBasedMongoQuery extends AbstractReactiveMongoQuery {
/**
* Creates a new {@link ReactiveStringBasedMongoQuery} for the given {@link String}, {@link MongoQueryMethod},
* {@link MongoOperations}, {@link SpelExpressionParser} and {@link EvaluationContextProvider}.
* {@link MongoOperations}, {@link SpelExpressionParser} and {@link QueryMethodEvaluationContextProvider}.
*
* @param query must not be {@literal null}.
* @param method must not be {@literal null}.

View File

@@ -40,7 +40,8 @@ import org.springframework.data.mongodb.core.convert.MongoTypeMapper;
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.MongoClient;
@@ -106,9 +107,10 @@ public class AbstractMongoConfigurationUnitTests {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class);
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
BasicMongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(Entity.class);
StandardEvaluationContext spElContext = (StandardEvaluationContext) ReflectionTestUtils.getField(entity, "context");
EvaluationContextProvider provider = (EvaluationContextProvider) ReflectionTestUtils.getField(entity,
"evaluationContextProvider");
assertThat(spElContext.getBeanResolver(), is(notNullValue()));
assertThat(provider, is(instanceOf(ExtensionAwareEvaluationContextProvider.class)));
context.close();
}

View File

@@ -18,6 +18,9 @@ package org.springframework.data.mongodb.config;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import example.first.First;
import example.second.Second;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -37,16 +40,14 @@ import org.springframework.data.mongodb.core.convert.MongoTypeMapper;
import org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
import org.springframework.test.util.ReflectionTestUtils;
import com.mongodb.Mongo;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import example.first.First;
import example.second.Second;
/**
* Unit tests for {@link AbstractReactiveMongoConfiguration}.
*
@@ -106,9 +107,10 @@ public class AbstractReactiveMongoConfigurationUnitTests {
AbstractApplicationContext context = new AnnotationConfigApplicationContext(SampleMongoConfiguration.class);
MongoMappingContext mappingContext = context.getBean(MongoMappingContext.class);
BasicMongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(Entity.class);
StandardEvaluationContext spElContext = (StandardEvaluationContext) ReflectionTestUtils.getField(entity, "context");
EvaluationContextProvider provider = (EvaluationContextProvider) ReflectionTestUtils.getField(entity,
"evaluationContextProvider");
assertThat(spElContext.getBeanResolver(), is(notNullValue()));
assertThat(provider, is(instanceOf(ExtensionAwareEvaluationContextProvider.class)));
context.close();
}

View File

@@ -15,14 +15,18 @@
*/
package org.springframework.data.mongodb.core.mapping;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,6 +35,8 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
import org.springframework.data.spel.spi.EvaluationContextExtension;
import org.springframework.data.util.ClassTypeInformation;
/**
@@ -68,11 +74,10 @@ public class BasicMongoPersistentEntityUnitTests {
provider.collectionName = "reference";
when(context.getBean("myBean")).thenReturn(provider);
when(context.containsBean("myBean")).thenReturn(true);
BasicMongoPersistentEntity<DynamicallyMapped> entity = new BasicMongoPersistentEntity<DynamicallyMapped>(
ClassTypeInformation.from(DynamicallyMapped.class));
entity.setApplicationContext(context);
entity.setEvaluationContextProvider(new ExtensionAwareEvaluationContextProvider(context));
assertThat(entity.getCollection(), is("reference"));
@@ -221,6 +226,17 @@ public class BasicMongoPersistentEntityUnitTests {
assertThat(entity.getCollection(), is("custom-collection"));
}
@Test // DATAMONGO-1874
public void usesEvaluationContextExtensionInDynamicDocumentName() {
BasicMongoPersistentEntity<MappedWithExtension> entity = new BasicMongoPersistentEntity<>(
ClassTypeInformation.from(MappedWithExtension.class));
entity.setEvaluationContextProvider(
new ExtensionAwareEvaluationContextProvider(Arrays.asList(new SampleExtension())));
assertThat(entity.getCollection()).isEqualTo("collectionName");
}
@Document("contacts")
class Contact {}
@@ -229,7 +245,7 @@ public class BasicMongoPersistentEntityUnitTests {
@Document("#{35}")
class Company {}
@Document("#{myBean.collectionName}")
@Document("#{@myBean.collectionName}")
class DynamicallyMapped {}
class CollectionProvider {
@@ -265,4 +281,30 @@ public class BasicMongoPersistentEntityUnitTests {
@AliasFor(annotation = Document.class, attribute = "collection")
String name() default "custom-collection";
}
// DATAMONGO-1874
@Document("#{myProperty}")
class MappedWithExtension {}
static class SampleExtension implements EvaluationContextExtension {
/*
* (non-Javadoc)
* @see org.springframework.data.spel.spi.EvaluationContextExtension#getExtensionId()
*/
@Override
public String getExtensionId() {
return "sampleExtension";
}
/*
* (non-Javadoc)
* @see org.springframework.data.spel.spi.EvaluationContextExtension#getProperties()
*/
@Override
public Map<String, Object> getProperties() {
return Collections.singletonMap("myProperty", "collectionName");
}
}
}

View File

@@ -26,11 +26,8 @@
</constructor-arg>
</bean>
</property>
<property name="evaluationContextProvider" ref="extensionAwareEvaluationContextProvider"/>
</bean>
<bean id="extensionAwareEvaluationContextProvider" class="org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider" autowire="constructor" />
<bean class="org.springframework.data.mongodb.repository.SampleEvaluationContextExtension" />
</beans>