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.