Skip to content

Commit 2f60d08

Browse files
DATAMONGO-2188 - Polishing.
Undo deprecation and transition to configuration option allowing to disable the index creation. Index creation will remain in the codebase as it is used in a lot of places to configure required geo index structures in MongoDB without which query execution would fail. Original Pull Request: #636
1 parent 5c79ff3 commit 2f60d08

14 files changed

+153
-28
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoConfigurationSupport.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public MongoMappingContext mongoMappingContext() throws ClassNotFoundException {
8787
mappingContext.setInitialEntitySet(getInitialEntitySet());
8888
mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
8989
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
90+
mappingContext.setAutoIndexCreation(autoIndexCreation());
9091

9192
return mappingContext;
9293
}
@@ -190,4 +191,16 @@ protected FieldNamingStrategy fieldNamingStrategy() {
190191
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy()
191192
: PropertyNameFieldNamingStrategy.INSTANCE;
192193
}
194+
195+
/**
196+
* Configure whether to automatically create indices for domain types by deriving the
197+
* {@link org.springframework.data.mongodb.core.index.IndexDefinition} from the entity or not.
198+
*
199+
* @return {@literal true} by default. <br />
200+
* <strong>INFO</strong>: As of 3.x the default will be set to {@literal false}.
201+
* @since 2.2
202+
*/
203+
protected boolean autoIndexCreation() {
204+
return true;
205+
}
193206
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3185,6 +3185,7 @@ public void onApplicationEvent(MappingContextEvent<?, ?> event) {
31853185

31863186
// Double check type as Spring infrastructure does not consider nested generics
31873187
if (entity instanceof MongoPersistentEntity) {
3188+
31883189
onCheckForIndexes((MongoPersistentEntity<?>) entity, subscriptionExceptionHandler);
31893190
}
31903191
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/IndexResolver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package org.springframework.data.mongodb.core.index;
1717

18-
import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexResolver.IndexDefinitionHolder;
1918
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
2019
import org.springframework.data.util.ClassTypeInformation;
2120
import org.springframework.data.util.TypeInformation;
@@ -36,6 +35,7 @@ public interface IndexResolver {
3635
*
3736
* @param mappingContext must not be {@literal null}.
3837
* @return the new {@link IndexResolver}.
38+
* @since 2.2
3939
*/
4040
static IndexResolver create(MongoMappingContext mappingContext) {
4141

@@ -51,7 +51,7 @@ static IndexResolver create(MongoMappingContext mappingContext) {
5151
* @param typeInformation
5252
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
5353
*/
54-
Iterable<? extends IndexDefinitionHolder> resolveIndexFor(TypeInformation<?> typeInformation);
54+
Iterable<? extends IndexDefinition> resolveIndexFor(TypeInformation<?> typeInformation);
5555

5656
/**
5757
* Find and create {@link IndexDefinition}s for properties of given {@link TypeInformation}. {@link IndexDefinition}s
@@ -61,7 +61,7 @@ static IndexResolver create(MongoMappingContext mappingContext) {
6161
* @return Empty {@link Iterable} in case no {@link IndexDefinition} could be resolved for type.
6262
* @see 2.2
6363
*/
64-
default Iterable<? extends IndexDefinitionHolder> resolveIndexFor(Class<?> entityType) {
64+
default Iterable<? extends IndexDefinition> resolveIndexFor(Class<?> entityType) {
6565
return resolveIndexFor(ClassTypeInformation.from(entityType));
6666
}
6767

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.core.index;
17+
18+
import java.util.Collections;
19+
import java.util.Map;
20+
import java.util.Set;
21+
import java.util.concurrent.ConcurrentHashMap;
22+
import java.util.concurrent.ConcurrentSkipListSet;
23+
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
26+
27+
/**
28+
* @author Christoph Strobl
29+
* @since 2.2
30+
*/
31+
class JustOnceLogger {
32+
33+
private static final Map<String, Set<String>> KNOWN_LOGS = new ConcurrentHashMap<>();
34+
private static final String AUTO_INDEX_CREATION_CONFIG_CHANGE;
35+
36+
static {
37+
AUTO_INDEX_CREATION_CONFIG_CHANGE = "Automatic index creation will be disabled by default as of Spring Data MongoDB 3.x."
38+
+ System.lineSeparator()
39+
+ "\tPlease use 'MongoMappingContext#setAutoIndexCreation(boolean)' or override 'MongoConfigurationSupport#autoIndexCreation()' to be explicit."
40+
+ System.lineSeparator()
41+
+ "\tHowever, we recommend setting up indices manually in an application ready block. You may use index derivation there as well."
42+
+ System.lineSeparator() + System.lineSeparator() //
43+
+ "\t> -----------------------------------------------------------------------------------------"
44+
+ System.lineSeparator() //
45+
+ "\t> @EventListener(ApplicationReadyEvent.class)" + System.lineSeparator() //
46+
+ "\t> public void initIndicesAfterStartup() {" + System.lineSeparator() //
47+
+ "\t>" + System.lineSeparator() //
48+
+ "\t> IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);" + System.lineSeparator()//
49+
+ "\t>" + System.lineSeparator() //
50+
+ "\t> IndexResolver resolver = new MongoPersistentEntityIndexResolver(mongoMappingContext);"
51+
+ System.lineSeparator() //
52+
+ "\t> resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);" + System.lineSeparator() //
53+
+ "\t> }" + System.lineSeparator() //
54+
+ "\t> -----------------------------------------------------------------------------------------"
55+
+ System.lineSeparator();
56+
}
57+
58+
static void logWarnIndexCreationConfigurationChange(String loggerName) {
59+
warnOnce(loggerName, AUTO_INDEX_CREATION_CONFIG_CHANGE);
60+
}
61+
62+
static void warnOnce(String loggerName, String message) {
63+
64+
Logger logger = LoggerFactory.getLogger(loggerName);
65+
if (!logger.isWarnEnabled()) {
66+
return;
67+
}
68+
69+
if (!KNOWN_LOGS.containsKey(loggerName)) {
70+
71+
KNOWN_LOGS.put(loggerName, new ConcurrentSkipListSet<>(Collections.singleton(message)));
72+
logger.warn(message);
73+
} else {
74+
75+
Set<String> messages = KNOWN_LOGS.get(loggerName);
76+
if (messages.contains(message)) {
77+
return;
78+
}
79+
80+
messages.add(message);
81+
logger.warn(message);
82+
}
83+
}
84+
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoMappingEventPublisher.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@
3636
* @author Jon Brisbin
3737
* @author Oliver Gierke
3838
* @author Mark Paluch
39-
* @deprecated since 2.2. Use {@link IndexOperations} to define and create indexes.
4039
*/
41-
@Deprecated
4240
public class MongoMappingEventPublisher implements ApplicationEventPublisher {
4341

4442
private final ApplicationListener<MappingContextEvent<?, ?>> indexCreator;

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ public void onApplicationEvent(MappingContextEvent<?, ?> event) {
110110

111111
// Double check type as Spring infrastructure does not consider nested generics
112112
if (entity instanceof MongoPersistentEntity) {
113+
113114
checkForIndexes((MongoPersistentEntity<?>) entity);
114115
}
115116
}
@@ -133,8 +134,16 @@ private void checkForIndexes(final MongoPersistentEntity<?> entity) {
133134
private void checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
134135

135136
if (entity.isAnnotationPresent(Document.class)) {
136-
for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
137+
for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
138+
139+
JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName());
140+
141+
IndexDefinitionHolder indexToCreate = indexDefinition instanceof IndexDefinitionHolder
142+
? (IndexDefinitionHolder) indexDefinition
143+
: new IndexDefinitionHolder("", indexDefinition, entity.getCollection());
144+
137145
createIndex(indexToCreate);
146+
138147
}
139148
}
140149
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreator.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,12 @@ private Mono<Void> checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
125125
List<Mono<?>> publishers = new ArrayList<>();
126126

127127
if (entity.isAnnotationPresent(Document.class)) {
128-
for (IndexDefinitionHolder indexToCreate : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
128+
for (IndexDefinition indexDefinition : indexResolver.resolveIndexFor(entity.getTypeInformation())) {
129+
130+
IndexDefinitionHolder indexToCreate = indexDefinition instanceof IndexDefinitionHolder
131+
? (IndexDefinitionHolder) indexDefinition
132+
: new IndexDefinitionHolder("", indexDefinition, entity.getCollection());
133+
129134
publishers.add(createIndex(indexToCreate));
130135
}
131136
}
@@ -135,6 +140,8 @@ private Mono<Void> checkForAndCreateIndexes(MongoPersistentEntity<?> entity) {
135140

136141
Mono<String> createIndex(IndexDefinitionHolder indexDefinition) {
137142

143+
JustOnceLogger.logWarnIndexCreationConfigurationChange(this.getClass().getName());
144+
138145
return operationsProvider.indexOps(indexDefinition.getCollection()).ensureIndex(indexDefinition) //
139146
.onErrorResume(ReactiveMongoPersistentEntityIndexCreator::isDataIntegrityViolation,
140147
e -> translateException(e, indexDefinition));

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/MongoMappingContext.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ public void setApplicationContext(ApplicationContext applicationContext) throws
104104
}
105105

106106
/**
107-
* Returns whether auto-index creation is enabled or disabled. Please note that auto-index creation is deprecated.
108-
* Index creation should happen at a well-defined time that is ideally controlled by the application itself.
107+
* Returns whether auto-index creation is enabled or disabled. <br />
108+
* <strong>NOTE:</strong>Index creation should happen at a well-defined time that is ideally controlled by the
109+
* application itself.
109110
*
110111
* @return {@literal true} when auto-index creation is enabled; {@literal false} otherwise.
111112
* @since 2.2
@@ -116,10 +117,11 @@ public boolean isAutoIndexCreation() {
116117
}
117118

118119
/**
119-
* Enables/disables auto-index creation. Please note that auto-index creation is deprecated. Index creation should
120-
* happen at a well-defined time that is ideally controlled by the application its
120+
* Enables/disables auto-index creation. <br />
121+
* <strong>NOTE:</strong>Index creation should happen at a well-defined time that is ideally controlled by the
122+
* application itself.
121123
*
122-
* @param autoCreateIndexes {@literal true} to enable auto-index creation. Enabled by default.
124+
* @param autoCreateIndexes set to {@literal false} to disable auto-index creation.
123125
* @since 2.2
124126
* @see org.springframework.data.mongodb.core.index.Indexed
125127
*/

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/IndexEnsuringQueryCreationListener.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@
4242
* @author Oliver Gierke
4343
* @author Mark Paluch
4444
* @author Christoph Strobl
45-
* @deprecated since 2.2. Use {@link org.springframework.data.mongodb.core.index.IndexOperations} to define and create
46-
* indexes.
4745
*/
48-
@Deprecated
4946
class IndexEnsuringQueryCreationListener implements QueryCreationListener<PartTreeMongoQuery> {
5047

5148
private static final Set<Type> GEOSPATIAL_TYPES = new HashSet<Type>(Arrays.asList(Type.NEAR, Type.WITHIN));

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/MongoRepositoryFactoryBean.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class MongoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
3535
extends RepositoryFactoryBeanSupport<T, S, ID> {
3636

3737
private @Nullable MongoOperations operations;
38-
@Deprecated private boolean createIndexesForQueryMethods = false;
38+
private boolean createIndexesForQueryMethods = false;
3939
private boolean mappingContextConfigured = false;
4040

4141
/**
@@ -60,10 +60,7 @@ public void setMongoOperations(MongoOperations operations) {
6060
* Configures whether to automatically create indexes for the properties referenced in a query method.
6161
*
6262
* @param createIndexesForQueryMethods the createIndexesForQueryMethods to set
63-
* @deprecated since 2.2. Use {@link org.springframework.data.mongodb.core.index.IndexOperations} to define and create
64-
* indexes.
6563
*/
66-
@Deprecated
6764
public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods) {
6865
this.createIndexesForQueryMethods = createIndexesForQueryMethods;
6966
}

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/ReactiveMongoRepositoryFactoryBean.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ public class ReactiveMongoRepositoryFactoryBean<T extends Repository<S, ID>, S,
4040
extends RepositoryFactoryBeanSupport<T, S, ID> {
4141

4242
private @Nullable ReactiveMongoOperations operations;
43-
44-
@Deprecated private boolean createIndexesForQueryMethods = false;
43+
private boolean createIndexesForQueryMethods = false;
4544
private boolean mappingContextConfigured = false;
4645

4746
/**
@@ -66,10 +65,7 @@ public void setReactiveMongoOperations(@Nullable ReactiveMongoOperations operati
6665
* Configures whether to automatically create indexes for the properties referenced in a query method.
6766
*
6867
* @param createIndexesForQueryMethods the createIndexesForQueryMethods to set
69-
* @deprecated since 2.2. Use {@link org.springframework.data.mongodb.core.index.IndexOperations} to define and create
70-
* indexes.
7168
*/
72-
@Deprecated
7369
public void setCreateIndexesForQueryMethods(boolean createIndexesForQueryMethods) {
7470
this.createIndexesForQueryMethods = createIndexesForQueryMethods;
7571
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void createsIndexWithFieldName() {
7373
assertThat(hasIndex("_firstname", IndexedPerson.class), is(true));
7474
}
7575

76-
@Test // DATAMONGO-237
76+
@Test // DATAMONGO-2188
7777
@DirtiesContext
7878
public void shouldNotCreateIndexOnIndexingDisabled() {
7979

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ public void indexPathOnLevelOneIsResolvedCorrectly() {
8787
assertIndexPathAndCollection("zero.indexedProperty", "One", indexDefinitions.get(0));
8888
}
8989

90-
@Test // DATAMONGO-899
90+
@Test // DATAMONGO-899, DATAMONGO-2188
9191
public void shouldResolveIndexViaClass() {
9292

9393
MongoMappingContext mappingContext = new MongoMappingContext();
9494
IndexResolver indexResolver = IndexResolver.create(mappingContext);
95-
Iterable<? extends IndexDefinitionHolder> definitions = indexResolver.resolveIndexFor(IndexOnLevelOne.class);
95+
Iterable<? extends IndexDefinition> definitions = indexResolver.resolveIndexFor(IndexOnLevelOne.class);
9696

9797
assertThat(definitions.iterator().hasNext(), is(true));
9898
}

src/main/asciidoc/reference/mapping.adoc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,29 @@ public class Person {
377377
====
378378

379379
IMPORTANT: The `@Id` annotation tells the mapper which property you want to use for the MongoDB `_id` property, and the `@Indexed` annotation tells the mapping framework to call `createIndex(…)` on that property of your document, making searches faster.
380+
Automatic index creation is only done for types annotated with `@Document`.
380381

381-
IMPORTANT: Automatic index creation is deprecated since version 2.2 because controlling the actual time of index creation is rather difficult. Index creation can be part of the application startup, happen during runtime or an out of band process. Therefore, Spring Data MongoDB backs off entirely and recommends index creation to happen either out of band or as part of the application startup using `IndexOperations`. Automatic index creation is still available and is is only done for types annotated with `@Document`.
382+
[NOTE]
383+
====
384+
To turn automatic index creation _OFF_ please override `autoIndexCreation()` in your configuration.
385+
[source,java]
386+
----
387+
@Configuration
388+
public class Config extends AbstractMongoClientConfiguration {
389+
390+
@Override
391+
public boolean autoIndexCreation() {
392+
return false;
393+
}
394+
395+
// ...
396+
}
397+
----
398+
====
399+
400+
IMPORTANT: Automatic index creation will be turned _OFF_ by default with the release of 3.x.
401+
We recommend index creation to happen either out of band or as part of the application startup using
402+
`IndexOperations`.
382403

383404
[[mapping-usage-annotations]]
384405
=== Mapping Annotation Overview

0 commit comments

Comments
 (0)