Skip to content

Commit 0c11a32

Browse files
committed
Fix MongoDB index creation API compatibility across Spring Data MongoDB versions
Use reflection to handle API differences between Spring Data MongoDB versions: - Spring Data MongoDB 4.2.x - 4.4.x: only ensureIndex() is available - Spring Data MongoDB 4.5.x+: createIndex() is the new API, ensureIndex is deprecated This fix ensures compatibility with both Spring Boot 3.4.x (MongoDB 4.4.x) and Spring Boot 3.5.x (MongoDB 4.5.x+), which are both officially supported versions. Fixes #4884
1 parent 10bc0a7 commit 0c11a32

File tree

1 file changed

+67
-7
lines changed
  • auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-mongodb/src/main/java/org/springframework/ai/model/chat/memory/repository/mongo/autoconfigure

1 file changed

+67
-7
lines changed

auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-mongodb/src/main/java/org/springframework/ai/model/chat/memory/repository/mongo/autoconfigure/MongoChatMemoryIndexCreatorAutoConfiguration.java

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.ai.model.chat.memory.repository.mongo.autoconfigure;
1818

19+
import java.lang.reflect.Method;
20+
1921
import org.slf4j.Logger;
2022
import org.slf4j.LoggerFactory;
2123

@@ -27,6 +29,8 @@
2729
import org.springframework.data.domain.Sort;
2830
import org.springframework.data.mongodb.core.MongoTemplate;
2931
import org.springframework.data.mongodb.core.index.Index;
32+
import org.springframework.data.mongodb.core.index.IndexDefinition;
33+
import org.springframework.data.mongodb.core.index.IndexOperations;
3034

3135
/**
3236
* Class responsible for creating proper MongoDB indices for the ChatMemory. Creates a
@@ -57,26 +61,82 @@ public MongoChatMemoryIndexCreatorAutoConfiguration(MongoTemplate mongoTemplate,
5761
public void initIndicesAfterStartup() {
5862
logger.info("Creating MongoDB indices for ChatMemory");
5963
// Create a main index
60-
this.mongoTemplate.indexOps(Conversation.class)
61-
.createIndex(new Index().on("conversationId", Sort.Direction.ASC).on("timestamp", Sort.Direction.DESC));
62-
64+
createMainIndex();
6365
createOrUpdateTtlIndex();
6466
}
6567

68+
private void createMainIndex() {
69+
var indexOps = this.mongoTemplate.indexOps(Conversation.class);
70+
var index = new Index().on("conversationId", Sort.Direction.ASC).on("timestamp", Sort.Direction.DESC);
71+
72+
// Use reflection to handle API differences across Spring Data MongoDB versions
73+
createIndexSafely(indexOps, index);
74+
}
75+
6676
private void createOrUpdateTtlIndex() {
6777
if (!this.mongoChatMemoryProperties.getTtl().isZero()) {
78+
var indexOps = this.mongoTemplate.indexOps(Conversation.class);
6879
// Check for existing TTL index
69-
this.mongoTemplate.indexOps(Conversation.class).getIndexInfo().forEach(idx -> {
80+
indexOps.getIndexInfo().forEach(idx -> {
7081
if (idx.getExpireAfter().isPresent()
7182
&& !idx.getExpireAfter().get().equals(this.mongoChatMemoryProperties.getTtl())) {
7283
logger.warn("Dropping existing TTL index, because TTL is different");
73-
this.mongoTemplate.indexOps(Conversation.class).dropIndex(idx.getName());
84+
indexOps.dropIndex(idx.getName());
7485
}
7586
});
76-
this.mongoTemplate.indexOps(Conversation.class)
77-
.createIndex(new Index().on("timestamp", Sort.Direction.ASC)
87+
// Use reflection to handle API differences across Spring Data MongoDB versions
88+
createIndexSafely(indexOps, new Index().on("timestamp", Sort.Direction.ASC)
7889
.expire(this.mongoChatMemoryProperties.getTtl()));
7990
}
8091
}
8192

93+
/**
94+
* Creates an index using reflection to handle API changes across different Spring
95+
* Data MongoDB versions:
96+
* <ul>
97+
* <li>Spring Data MongoDB 4.2.x - 4.4.x: only {@code ensureIndex(IndexDefinition)}
98+
* is available</li>
99+
* <li>Spring Data MongoDB 4.5.x+: {@code createIndex(IndexDefinition)} is the new
100+
* API, {@code ensureIndex} is deprecated</li>
101+
* </ul>
102+
* @param indexOps the IndexOperations instance
103+
* @param index the index definition
104+
* @throws IllegalStateException if neither method is available or invocation fails
105+
*/
106+
private void createIndexSafely(IndexOperations indexOps, IndexDefinition index) {
107+
try {
108+
// Try new API (Spring Data MongoDB 4.5.x+)
109+
Method method = IndexOperations.class.getMethod("createIndex", IndexDefinition.class);
110+
method.invoke(indexOps, index);
111+
logger.debug("Created index using createIndex() method");
112+
return;
113+
}
114+
catch (NoSuchMethodException createIndexNotFound) {
115+
// Fall back to old API (Spring Data MongoDB 4.2.x - 4.4.x)
116+
try {
117+
Method method = IndexOperations.class.getMethod("ensureIndex", IndexDefinition.class);
118+
method.invoke(indexOps, index);
119+
logger.debug("Created index using ensureIndex() method");
120+
return;
121+
}
122+
catch (NoSuchMethodException ensureIndexNotFound) {
123+
// Neither method exists - this should never happen with supported versions
124+
String message = "Neither createIndex() nor ensureIndex() method found on IndexOperations. "
125+
+ "This may indicate an unsupported Spring Data MongoDB version.";
126+
logger.error(message);
127+
throw new IllegalStateException(message, ensureIndexNotFound);
128+
}
129+
catch (ReflectiveOperationException ex) {
130+
String message = "Failed to invoke ensureIndex() method";
131+
logger.error(message, ex);
132+
throw new IllegalStateException(message, ex);
133+
}
134+
}
135+
catch (ReflectiveOperationException ex) {
136+
String message = "Failed to invoke createIndex() method";
137+
logger.error(message, ex);
138+
throw new IllegalStateException(message, ex);
139+
}
140+
}
141+
82142
}

0 commit comments

Comments
 (0)