Skip to content

Commit 51a469b

Browse files
committed
DATAMONGO-412 - General overhaul of the JavaConfig base class.
Refactored JavaConfig base class to reflect the XML namespace a bit more closely (esp. regarding configuration of custom converters and thus registering "simple" types). Prevent duplicate invocation of getUserCredentials(). Added JavaDoc to explain which configuration methods use which other ones to ease detailed configuration.
1 parent 9f2b1f4 commit 51a469b

File tree

2 files changed

+124
-34
lines changed

2 files changed

+124
-34
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2011 the original author or authors.
2+
* Copyright 2011-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,88 +15,176 @@
1515
*/
1616
package org.springframework.data.mongodb.config;
1717

18+
import java.util.Collections;
1819
import java.util.HashSet;
1920
import java.util.Set;
2021

21-
import com.mongodb.Mongo;
2222
import org.springframework.beans.factory.config.BeanDefinition;
2323
import org.springframework.context.annotation.Bean;
2424
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
2525
import org.springframework.context.annotation.Configuration;
26+
import org.springframework.core.convert.converter.Converter;
2627
import org.springframework.core.type.filter.AnnotationTypeFilter;
2728
import org.springframework.data.annotation.Persistent;
2829
import org.springframework.data.authentication.UserCredentials;
29-
import org.springframework.data.mongodb.MongoDbFactory;
3030
import org.springframework.data.mongodb.core.MongoTemplate;
3131
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
32+
import org.springframework.data.mongodb.core.convert.CustomConversions;
3233
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
3334
import org.springframework.data.mongodb.core.mapping.Document;
3435
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
3536
import org.springframework.util.ClassUtils;
3637
import org.springframework.util.StringUtils;
3738

39+
import com.mongodb.Mongo;
40+
41+
/**
42+
* Base class for Spring Data Mongo configuration using JavaConfig.
43+
*
44+
* @author Mark Pollack
45+
* @author Oliver Gierke
46+
*/
3847
@Configuration
3948
public abstract class AbstractMongoConfiguration {
4049

41-
public abstract String getDatabaseName();
50+
/**
51+
* Return the name of the database to connect to.
52+
*
53+
* @return must not be {@literal null}.
54+
*/
55+
protected abstract String getDatabaseName();
4256

57+
/**
58+
* Return the {@link Mongo} instance to connect to.
59+
*
60+
* @return
61+
* @throws Exception
62+
*/
4363
@Bean
4464
public abstract Mongo mongo() throws Exception;
4565

66+
/**
67+
* Creates a {@link MongoTemplate}.
68+
*
69+
* @return
70+
* @throws Exception
71+
*/
4672
@Bean
4773
public MongoTemplate mongoTemplate() throws Exception {
4874
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
4975
}
5076

77+
/**
78+
* Creates a {@link SimpleMongoDbFactory} to be used by the {@link MongoTemplate}. Will use the {@link Mongo} instance
79+
* configured in {@link #mongo()}.
80+
*
81+
* @see #mongo()
82+
* @see #mongoTemplate()
83+
* @return
84+
* @throws Exception
85+
*/
5186
@Bean
52-
public MongoDbFactory mongoDbFactory() throws Exception {
53-
if (getUserCredentials() == null) {
87+
public SimpleMongoDbFactory mongoDbFactory() throws Exception {
88+
89+
UserCredentials creadentials = getUserCredentials();
90+
91+
if (creadentials == null) {
5492
return new SimpleMongoDbFactory(mongo(), getDatabaseName());
5593
} else {
56-
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), getUserCredentials());
94+
return new SimpleMongoDbFactory(mongo(), getDatabaseName(), creadentials);
5795
}
5896
}
5997

60-
public String getMappingBasePackage() {
61-
return "";
98+
/**
99+
* Return the base package to scan for mapped {@link Document}s.
100+
*
101+
* @return
102+
*/
103+
protected String getMappingBasePackage() {
104+
return null;
62105
}
63106

64-
public UserCredentials getUserCredentials() {
107+
/**
108+
* Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall
109+
* be used.
110+
*
111+
* @return
112+
*/
113+
protected UserCredentials getUserCredentials() {
65114
return null;
66115
}
67116

117+
/**
118+
* Creates a {@link MongoMappingContext} equipped with entity classes scanned from the mapping base package.
119+
*
120+
* @see #getMappingBasePackage()
121+
* @return
122+
* @throws ClassNotFoundException
123+
*/
68124
@Bean
69-
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException, LinkageError {
125+
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
126+
70127
MongoMappingContext mappingContext = new MongoMappingContext();
71-
String basePackage = getMappingBasePackage();
72-
if (StringUtils.hasText(basePackage)) {
73-
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
74-
false);
75-
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
76-
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
128+
mappingContext.setInitialEntitySet(getInitialEntitySet());
129+
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
130+
mappingContext.afterPropertiesSet();
77131

78-
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
79-
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
80-
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), mappingContext.getClass()
81-
.getClassLoader()));
82-
}
83-
mappingContext.setInitialEntitySet(initialEntitySet);
84-
}
85132
return mappingContext;
86133
}
87134

135+
/**
136+
* Register custom {@link Converter}s in a {@link CustomConversions} object if required. These
137+
* {@link CustomConversions} will be registered with the {@link #mappingMongoConverter()} and
138+
* {@link #mongoMappingContext()}. Returns an empty {@link CustomConversions} instance by default.
139+
*
140+
* @return must not be {@literal null}.
141+
*/
142+
@Bean
143+
public CustomConversions customConversions() {
144+
return new CustomConversions(Collections.emptyList());
145+
}
146+
147+
/**
148+
* Creates a {@link MappingMongoConverter} using the configured {@link #mongoDbFactory()} and
149+
* {@link #mongoMappingContext()}. Will get {@link #customConversions()} applied.
150+
*
151+
* @see #customConversions()
152+
* @see #mongoMappingContext()
153+
* @see #mongoDbFactory()
154+
* @return
155+
* @throws Exception
156+
*/
88157
@Bean
89158
public MappingMongoConverter mappingMongoConverter() throws Exception {
90159
MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), mongoMappingContext());
91-
afterMappingMongoConverterCreation(converter);
160+
converter.setCustomConversions(customConversions());
92161
return converter;
93162
}
94163

95164
/**
96-
* Hook that allows post-processing after the MappingMongoConverter has been successfully created.
165+
* Scans the mapping base package for classes annotated with {@link Document}.
97166
*
98-
* @param converter
167+
* @see #getMappingBasePackage()
168+
* @return
169+
* @throws ClassNotFoundException
99170
*/
100-
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
171+
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
172+
173+
String basePackage = getMappingBasePackage();
174+
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
175+
176+
if (StringUtils.hasText(basePackage)) {
177+
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
178+
false);
179+
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
180+
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
181+
182+
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
183+
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(),
184+
AbstractMongoConfiguration.class.getClassLoader()));
185+
}
186+
}
187+
188+
return initialEntitySet;
101189
}
102190
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java

+8-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import java.util.ArrayList;
44
import java.util.List;
5-
import com.mongodb.Mongo;
5+
66
import org.springframework.context.annotation.Bean;
77
import org.springframework.core.convert.converter.Converter;
88
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
99
import org.springframework.data.mongodb.core.convert.CustomConversions;
10-
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
10+
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
11+
12+
import com.mongodb.Mongo;
1113

1214
public class TestMongoConfiguration extends AbstractMongoConfiguration {
1315

@@ -24,15 +26,15 @@ public Mongo mongo() throws Exception {
2426

2527
@Override
2628
public String getMappingBasePackage() {
27-
return "org.springframework.data.mongodb.core.core.mapping";
29+
return MongoMappingContext.class.getPackage().getName();
2830
}
2931

3032
@Override
31-
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
33+
public CustomConversions customConversions() {
34+
3235
List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
3336
converters.add(new org.springframework.data.mongodb.core.PersonReadConverter());
3437
converters.add(new org.springframework.data.mongodb.core.PersonWriteConverter());
35-
converter.setCustomConversions(new CustomConversions(converters));
38+
return new CustomConversions(converters);
3639
}
37-
3840
}

0 commit comments

Comments
 (0)