Skip to content

Commit 034ce0a

Browse files
odrotbohmphilwebb
authored andcommitted
Setup MongoMappingContext setInitialEntitySet
Update MongoDataAutoConfiguration to set the MongoMappingContext initialEntitySet by scanning for @document or @Persistent classes from AutoConfigurationPackages. Fixes gh-2107
1 parent a27217a commit 034ce0a

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoDataAutoConfiguration.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,30 @@
1717
package org.springframework.boot.autoconfigure.mongo;
1818

1919
import java.net.UnknownHostException;
20+
import java.util.Collection;
21+
import java.util.Collections;
22+
import java.util.HashSet;
23+
import java.util.Set;
2024

2125
import org.springframework.beans.factory.BeanFactory;
2226
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
2327
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.beans.factory.config.BeanDefinition;
29+
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
2430
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
2531
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2632
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2733
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2834
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2935
import org.springframework.context.annotation.Bean;
36+
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
3037
import org.springframework.context.annotation.Configuration;
38+
import org.springframework.core.env.Environment;
39+
import org.springframework.core.io.ResourceLoader;
40+
import org.springframework.core.type.filter.AnnotationTypeFilter;
3141
import org.springframework.dao.DataAccessException;
3242
import org.springframework.dao.support.PersistenceExceptionTranslator;
43+
import org.springframework.data.annotation.Persistent;
3344
import org.springframework.data.authentication.UserCredentials;
3445
import org.springframework.data.mongodb.MongoDbFactory;
3546
import org.springframework.data.mongodb.core.MongoTemplate;
@@ -39,9 +50,11 @@
3950
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
4051
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
4152
import org.springframework.data.mongodb.core.convert.MongoConverter;
53+
import org.springframework.data.mongodb.core.mapping.Document;
4254
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
4355
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
4456
import org.springframework.util.Assert;
57+
import org.springframework.util.ClassUtils;
4558
import org.springframework.util.StringUtils;
4659

4760
import com.mongodb.DB;
@@ -71,6 +84,12 @@ public class MongoDataAutoConfiguration {
7184
@Autowired
7285
private MongoProperties properties;
7386

87+
@Autowired
88+
private Environment environment;
89+
90+
@Autowired
91+
private ResourceLoader resourceLoader;
92+
7493
@Bean
7594
@ConditionalOnMissingBean
7695
public MongoDbFactory mongoDbFactory(Mongo mongo) throws Exception {
@@ -111,8 +130,42 @@ public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory,
111130

112131
@Bean
113132
@ConditionalOnMissingBean
114-
public MongoMappingContext mongoMappingContext() {
115-
return new MongoMappingContext();
133+
public MongoMappingContext mongoMappingContext(BeanFactory beanFactory)
134+
throws ClassNotFoundException {
135+
MongoMappingContext context = new MongoMappingContext();
136+
context.setInitialEntitySet(getInitialEntitySet(beanFactory));
137+
return context;
138+
}
139+
140+
private Set<Class<?>> getInitialEntitySet(BeanFactory beanFactory)
141+
throws ClassNotFoundException {
142+
Set<Class<?>> entitySet = new HashSet<Class<?>>();
143+
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(
144+
false);
145+
scanner.setEnvironment(this.environment);
146+
scanner.setResourceLoader(this.resourceLoader);
147+
scanner.addIncludeFilter(new AnnotationTypeFilter(Document.class));
148+
scanner.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
149+
for (String basePackage : getMappingBasePackages(beanFactory)) {
150+
if (StringUtils.hasText(basePackage)) {
151+
for (BeanDefinition candidate : scanner
152+
.findCandidateComponents(basePackage)) {
153+
entitySet.add(ClassUtils.forName(candidate.getBeanClassName(),
154+
MongoDataAutoConfiguration.class.getClassLoader()));
155+
}
156+
}
157+
}
158+
return entitySet;
159+
}
160+
161+
private static Collection<String> getMappingBasePackages(BeanFactory beanFactory) {
162+
try {
163+
return AutoConfigurationPackages.get(beanFactory);
164+
}
165+
catch (IllegalStateException ex) {
166+
// no auto-configuration package registered yet
167+
return Collections.emptyList();
168+
}
116169
}
117170

118171
@Bean

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoDataAutoConfigurationTests.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,37 @@
1717
package org.springframework.boot.autoconfigure.mongo;
1818

1919
import java.util.Arrays;
20+
import java.util.Set;
2021

22+
import org.hamcrest.Matchers;
2123
import org.junit.After;
2224
import org.junit.Test;
25+
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
2326
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
27+
import org.springframework.boot.autoconfigure.data.mongo.city.City;
2428
import org.springframework.boot.test.EnvironmentTestUtils;
2529
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2630
import org.springframework.context.annotation.Bean;
2731
import org.springframework.context.annotation.Configuration;
2832
import org.springframework.core.convert.converter.Converter;
2933
import org.springframework.data.mongodb.core.MongoTemplate;
3034
import org.springframework.data.mongodb.core.convert.CustomConversions;
35+
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
3136
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
37+
import org.springframework.test.util.ReflectionTestUtils;
3238

3339
import com.mongodb.Mongo;
3440

41+
import static org.hamcrest.Matchers.hasSize;
3542
import static org.junit.Assert.assertEquals;
43+
import static org.junit.Assert.assertThat;
3644
import static org.junit.Assert.assertTrue;
3745

3846
/**
3947
* Tests for {@link MongoDataAutoConfiguration}.
4048
*
4149
* @author Josh Long
50+
* @author Oliver Gierke
4251
*/
4352
public class MongoDataAutoConfigurationTests {
4453

@@ -82,14 +91,34 @@ public void customConversions() throws Exception {
8291
.canConvert(Mongo.class, Boolean.class));
8392
}
8493

94+
@Test
95+
public void usesAutoConfigurationPackageToPickUpDocumentTypes() {
96+
this.context = new AnnotationConfigApplicationContext();
97+
String cityPackage = City.class.getPackage().getName();
98+
AutoConfigurationPackages.register(this.context, cityPackage);
99+
this.context.register(MongoAutoConfiguration.class,
100+
MongoDataAutoConfiguration.class);
101+
this.context.refresh();
102+
assertDomainTypesDiscovered(this.context.getBean(MongoMappingContext.class),
103+
City.class);
104+
}
105+
106+
@SuppressWarnings({ "unchecked", "rawtypes" })
107+
private static void assertDomainTypesDiscovered(MongoMappingContext mappingContext,
108+
Class<?>... types) {
109+
Set<Class> initialEntitySet = (Set<Class>) ReflectionTestUtils.getField(
110+
mappingContext, "initialEntitySet");
111+
assertThat(initialEntitySet, hasSize(types.length));
112+
assertThat(initialEntitySet, Matchers.<Class> hasItems(types));
113+
}
114+
85115
@Configuration
86116
static class CustomConversionsConfig {
87117

88118
@Bean
89119
public CustomConversions customConversions() {
90120
return new CustomConversions(Arrays.asList(new MyConverter()));
91121
}
92-
93122
}
94123

95124
private static class MyConverter implements Converter<Mongo, Boolean> {
@@ -100,4 +129,5 @@ public Boolean convert(Mongo source) {
100129
}
101130

102131
}
132+
103133
}

0 commit comments

Comments
 (0)