Problems
We are using Azure Cosmos/MongoDB as our database, and using Spring Data Mongo for Repository. The Spring Boot application is using Spring Boot Actuator to monitor the health of MongoDB connection.
When we upgrade Spring Boot version from 3.1.5 to 3.3.5, it breaks actuator health check for MongoDB. The error message is:
2024-11-07T16:10:14.835Z WARN 1 --- [identity-provider] [mcat-handler-16] [672ce666b3bf38cd049746bd76ff1415-049746bd76ff1415] o.s.b.a.data.mongo.MongoHealthIndicator : MongoDB health check failed
org.springframework.dao.InvalidDataAccessApiUsageException: Command failed with error 115 (CommandNotSupported): 'Command hello not supported.' on server global-cosmos-mongo-int-northeurope.mongo.cosmos.azure.com:10255. The full response is {"ok": 0.0, "errmsg": "Command hello not supported.", "code": 115, "codeName": "CommandNotSupported"}
at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:124) ~[spring-data-mongodb-4.3.5.jar!/:4.3.5]
at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:3008) ~[spring-data-mongodb-4.3.5.jar!/:4.3.5]
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:584) ~[spring-data-mongodb-4.3.5.jar!/:4.3.5]
Root Cause
The root cause is that Cosmos/MongoDB server does not support the hello command, which is still on version 4.2 by the time. The hello command is used by the MongoHealthIndicator to check the MongoDB server status, supported by MongoDB since version 5.
Solution
To fix the issue, we need to customize the MongoHealthIndicator to use a different command to check the MongoDB server status.
package com.example.demo;
import org.bson.Document;
import org.springframework.boot.actuate.data.mongo.MongoHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.util.Assert;
public class CustomMongoHealthIndicator extends MongoHealthIndicator {
private final MongoTemplate mongoTemplate;
public CustomMongoHealthIndicator(MongoTemplate mongoTemplate) {
super(mongoTemplate);
Assert.notNull(mongoTemplate, "MongoTemplate must not be null");
this.mongoTemplate = mongoTemplate;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
Document result = this.mongoTemplate.executeCommand("{ isMaster: 1 }");
builder.up().withDetail("maxWireVersion", result.getInteger("maxWireVersion"));
}
}
Then, we need to register the CustomMongoHealthIndicator bean in the Spring Boot application.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HealthIndicatorConfig {
@Bean
public CustomMongoHealthIndicator customMongoHealthIndicator(MongoTemplate mongoTemplate) {
return new CustomMongoHealthIndicator(mongoTemplate);
}
}
Now, the CustomMongoHealthIndicator will use the isMaster command to check the MongoDB server status, which is used in old Spring Actuator 3.1, and supported by Cosmos/MongoDB server 4.2.
Click to load Disqus comments