spring, tips,

Customize Spring Actuator MongoDB Health Check

Cui Cui Follow Nov 08, 2024 · 2 mins read
Customize Spring Actuator MongoDB Health Check

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.

Join Newsletter
Get the latest news right in your inbox. We never spam!
Cui
Written by Cui Follow
Hi, I am Z, the coder for cuizhanming.com!