Skip to content

Conversation

@Suraj-kumar00
Copy link
Contributor

@Suraj-kumar00 Suraj-kumar00 commented Jan 13, 2026

  • Enhanced /health endpoint to show per-component status
  • Added type, host, port, database, version, and response time details
  • Returns error messages and types when components are down
  • Added MongoDB dependency and health check support

📋 Description

JIRA ID:

Please provide a summary of the change and the motivation behind it. Include relevant context and details.


✅ Type of Change

  • 🐞 Bug fix (non-breaking change which resolves an issue)
  • New feature (non-breaking change which adds functionality)
  • 🔥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 🛠 Refactor (change that is neither a fix nor a new feature)
  • ⚙️ Config change (configuration file or build script updates)
  • 📚 Documentation (updates to docs or readme)
  • 🧪 Tests (adding new or updating existing tests)
  • 🎨 UI/UX (changes that affect the user interface)
  • 🚀 Performance (improves performance)
  • 🧹 Chore (miscellaneous changes that don't modify src or test files)

ℹ️ Additional Information

Please describe how the changes were tested, and include any relevant screenshots, logs, or other information that provides additional context.

Summary by CodeRabbit

  • New Features

    • System health checks now include MongoDB alongside MySQL and Redis
    • Health responses show per-component metrics: response times, connection details, and DB versions
    • Overall health responses include a timestamp
    • Improved error handling with component-specific error details
  • Chores

    • Added MongoDB dependency and configuration properties
    • Added GitHub Actions step to fetch the base branch before workflow setup

✏️ Tip: You can customize this high-level summary in your review settings.

- Enhanced /health endpoint to show per-component status
- Added type, host, port, database, version, and response time details
- Returns error messages and types when components are down
- Added MongoDB dependency and health check support
@coderabbitai
Copy link

coderabbitai bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

Adds MongoDB support and wiring: a Maven dependency and application properties, plus a refactored HealthService that performs detailed health checks for MySQL, Redis, and MongoDB returning structured component statuses and a timestamped overall response.

Changes

Cohort / File(s) Summary
Dependency Management
pom.xml
Added org.springframework.boot:spring-boot-starter-data-mongodb dependency (no explicit version; inherits from parent).
Configuration
src/main/resources/application.properties
Added MongoDB configuration keys: host, port, and database (mongodb-container, 27017, amrit).
Health Check Enhancement
src/main/java/com/iemr/admin/service/health/HealthService.java
Reworked health endpoint to check MySQL, Redis, and MongoDB; returns structured component maps (status, host, port, database, responseTimeMs, version), adds timestamp, detailed error reporting, and helper/version extraction methods.
CI Workflow
.github/workflows/commit-lint.yml
Added a "Fetch base branch" step to fetch the PR base ref before Node.js setup.

Sequence Diagram

sequenceDiagram
    participant Client
    participant HealthService
    participant MySQL
    participant Redis
    participant MongoDB

    Client->>HealthService: GET /health
    par Parallel Health Checks
        HealthService->>MySQL: connect, simple query, fetch version
        MySQL-->>HealthService: status (+ version / error)
        HealthService->>Redis: PING, INFO for version
        Redis-->>HealthService: PONG (+ version / error)
        HealthService->>MongoDB: ping command, buildInfo for version
        MongoDB-->>HealthService: pong (+ version / error)
    end
    HealthService->>HealthService: assemble components map with<br/>host, port, database, responseTimeMs, version, timestamp
    HealthService-->>Client: JSON health response with components and timestamp
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I nibble bytes and tally pings,

Three stores sing as my whisker rings.
Mongo hops in, joins Redis and MySQL,
Health checks dance and timestamps swell.
Cheers — a rabbit's code-time spell!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add detailed component health checks for MySQL, Redis, and MongoDB' directly and clearly summarizes the main change in the changeset, which is enhancing the health check endpoint to provide detailed per-component status information for three data stores.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b286c6 and d6a362c.

📒 Files selected for processing (1)
  • .github/workflows/commit-lint.yml
🔇 Additional comments (1)
.github/workflows/commit-lint.yml (1)

20-22: LGTM!

This step correctly ensures the base branch ref is available when the PR originates from a fork repository. Since actions/checkout fetches from the fork's repository, the origin/<base> ref may not exist locally, which could cause issues for commitlint when comparing commits. This explicit fetch resolves that edge case.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In @src/main/java/com/iemr/admin/service/health/HealthService.java:
- Around line 180-184: The Redis health check in HealthService currently calls
redisTemplate.execute with connection.ping() without any timeout; update the
health check (the method using redisTemplate.execute/RedisCallback) to enforce a
timeout by either configuring a connection timeout on the RedisConnectionFactory
used by redisTemplate (set the client/connection timeout property) or wrap the
execute call in a cancellable timed task (e.g., submit a
Callable/CompletableFuture that calls redisTemplate.execute(...) and use
get(timeout, unit)) and handle TimeoutException by treating Redis as unhealthy
and logging the timeout; ensure you reference redisTemplate and the
HealthService health-check method when making the change and propagate/return a
failure status on timeout.
- Around line 230-232: The pingResult null-check is incomplete and calling
pingResult.getDouble("ok") can return null and cause an NPE; change the check to
safely retrieve and verify the "ok" field (for example: use pingResult.get("ok",
Number.class) or pingResult.get("ok", Double.class'), ensure the returned value
is non-null, then call .doubleValue() and compare to 1.0), e.g., obtain Number
ok = pingResult.get("ok", Number.class); and use if (pingResult != null && ok !=
null && ok.doubleValue() == 1.0) to avoid auto-unboxing NPE in the HealthService
ping logic that calls mongoTemplate.getDb().runCommand.
- Around line 228-230: The MongoDB ping in HealthService
(mongoTemplate.getDb().runCommand(...)) lacks a timeout and can hang; add a
timeout by either supplying a maxTimeMS to the ping command (e.g., include a
maxTimeMS value in the Document/BSON passed to runCommand) or configure the
MongoClient's socket/timeout settings (MongoClientSettings socketTimeout or
serverSelectionTimeout) used by mongoTemplate; update the runCommand invocation
or the MongoClient configuration so the health check uses a bounded timeout
(e.g., 2–3s) to mirror the MySQL check.
- Around line 121-126: The health endpoint currently always adds sensitive DB
details via details.put("type", "MySQL"), details.put("host",
extractHost(dbUrl)), details.put("port", extractPort(dbUrl)),
details.put("database", extractDatabaseName(dbUrl)) (and similar Redis/MongoDB
blocks) and returns exception messages/classes; make detail exposure conditional
on a new config flag (e.g., boolean exposeHealthDetails) read from properties,
and wrap each sensitive addition behind if (exposeHealthDetails) checks so
host/port/database names are only added when true; for exceptions, stop
returning exception.getMessage()/getClass() to the HTTP response—keep internal
logging (use logger.error with the caught exception) and return a generic error
string in the health response; apply these changes to the MySQL block
(details.put calls), Redis and MongoDB detail blocks, and the three exception
handlers that currently expose exception details.

In @src/main/resources/application.properties:
- Around line 77-81: Add MongoDB authentication properties to the existing
spring.data.mongodb.* configuration: include spring.data.mongodb.username and
spring.data.mongodb.password (sourced from environment variables like
MONGO_USER/MONGO_PASSWORD), set spring.data.mongodb.authentication-database
(e.g., admin), and optionally enable TLS with
spring.data.mongodb.ssl.enabled=true for production; ensure credentials are
injected via external config or secrets manager (do not hardcode) and update any
connection-handling code to use these properties.
🧹 Nitpick comments (1)
src/main/java/com/iemr/admin/service/health/HealthService.java (1)

305-324: Consider using URI parsing for robustness.

The manual string parsing works for standard MySQL JDBC URLs but could fail on edge cases (e.g., URLs with credentials, IPv6 addresses). Consider using Java's URI class or extracting connection metadata directly from the DataSource/Connection metadata.

♻️ Alternative approach using Connection metadata
private String extractHost(String jdbcUrl) {
    try {
        // Try to get from connection metadata first
        try (Connection conn = dataSource.getConnection()) {
            DatabaseMetaData meta = conn.getMetaData();
            String url = meta.getURL();
            // Parse from metadata URL or use existing logic
        }
    } catch (Exception e) {
        // Fall back to string parsing
    }
    // ... existing string parsing as fallback
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c56ce2d and 4b286c6.

📒 Files selected for processing (3)
  • pom.xml
  • src/main/java/com/iemr/admin/service/health/HealthService.java
  • src/main/resources/application.properties
🔇 Additional comments (4)
src/main/java/com/iemr/admin/service/health/HealthService.java (3)

57-76: Good use of optional autowiring and default values.

The @Autowired(required = false) for MongoTemplate properly handles deployments where MongoDB isn't configured. Default values in @Value annotations provide sensible fallbacks.


78-114: LGTM! Well-structured health check orchestration.

The method properly:

  • Uses LinkedHashMap for consistent JSON ordering
  • Conditionally checks optional components (Redis, MongoDB)
  • Aggregates overall health status from component statuses

263-299: LGTM! Version retrieval methods are well-implemented.

Good practices observed:

  • Non-critical operations with graceful degradation (return null on failure)
  • Debug-level logging for troubleshooting without cluttering logs
  • Proper resource management with try-with-resources for MySQL
pom.xml (1)

203-206: MongoDB dependency correctly added.

The dependency inherits its version from the Spring Boot parent (3.2.2), which is the standard approach for Spring Boot starters and ensures compatibility with other Spring Data components. The placement alongside the Redis starter is appropriate.

Comment on lines +121 to +126
// Add connection details
details.put("type", "MySQL");
details.put("host", extractHost(dbUrl));
details.put("port", extractPort(dbUrl));
details.put("database", extractDatabaseName(dbUrl));

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check for health endpoint configuration and security setup
rg -n -C3 "health|HealthController|HealthService" --type=java | head -100

Repository: PSMRI/Admin-API

Length of output: 10338


🏁 Script executed:

# Look for Spring Boot Actuator configuration
find . -type f \( -name "application.properties" -o -name "application.yml" -o -name "application.yaml" \) -exec grep -l "health\|actuator" {} \;

Repository: PSMRI/Admin-API

Length of output: 41


🏁 Script executed:

# Check for Spring Security configuration
rg -n "EnableWebSecurity|SecurityFilterChain|authorizeRequests" --type=java | head -50

Repository: PSMRI/Admin-API

Length of output: 41


🏁 Script executed:

# Look for any request mapping or endpoint configuration
rg -n -C2 "@RequestMapping|@GetMapping|@PostMapping" --type=java -g "*/controller/*" | head -100

Repository: PSMRI/Admin-API

Length of output: 207


🏁 Script executed:

# Check the actual HealthService implementation
fd -t f "HealthService.java" --exec cat -n {} \;

Repository: PSMRI/Admin-API

Length of output: 16914


🏁 Script executed:

# Find the controller that exposes the health endpoint
rg -n "@RequestMapping|@GetMapping|@RestController|@Controller" -A5 --type=java | grep -A5 "health"

Repository: PSMRI/Admin-API

Length of output: 1796


🏁 Script executed:

# Look for application configuration files
find . -type f \( -name "*.properties" -o -name "*.yml" -o -name "*.yaml" \) | head -20

Repository: PSMRI/Admin-API

Length of output: 453


Restrict database connection details exposure in public health endpoint.

The /health endpoint is intentionally public (JWT validation explicitly skipped in JwtUserIdValidationFilter), yet exposes database host, port, and database names for all components (MySQL, Redis, MongoDB). Additionally, exception messages and class names are exposed, which could leak version information. This aids reconnaissance and should be restricted.

Consider either:

  1. Restricting detail exposure to authenticated/internal requests
  2. Making detail exposure configurable via a property

This applies across all three database components (MySQL at lines 122-125, Redis at lines 177-178, MongoDB at lines 224-226, plus exception details at lines 163-164, 210-211, and 256-257).

🤖 Prompt for AI Agents
In @src/main/java/com/iemr/admin/service/health/HealthService.java around lines
121 - 126, The health endpoint currently always adds sensitive DB details via
details.put("type", "MySQL"), details.put("host", extractHost(dbUrl)),
details.put("port", extractPort(dbUrl)), details.put("database",
extractDatabaseName(dbUrl)) (and similar Redis/MongoDB blocks) and returns
exception messages/classes; make detail exposure conditional on a new config
flag (e.g., boolean exposeHealthDetails) read from properties, and wrap each
sensitive addition behind if (exposeHealthDetails) checks so host/port/database
names are only added when true; for exceptions, stop returning
exception.getMessage()/getClass() to the HTTP response—keep internal logging
(use logger.error with the caught exception) and return a generic error string
in the health response; apply these changes to the MySQL block (details.put
calls), Redis and MongoDB detail blocks, and the three exception handlers that
currently expose exception details.

Comment on lines 180 to +184
try {
String pong = redisTemplate.execute((RedisCallback<String>) connection -> connection.ping());

// Use ping() from RedisConnection directly
String pong = redisTemplate.execute((RedisCallback<String>) connection ->
connection.ping()
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing timeout for Redis health check.

The Redis ping() operation lacks an explicit timeout. Consider configuring a connection timeout in Redis properties or wrapping the call with a timeout mechanism to prevent blocking.

🤖 Prompt for AI Agents
In @src/main/java/com/iemr/admin/service/health/HealthService.java around lines
180 - 184, The Redis health check in HealthService currently calls
redisTemplate.execute with connection.ping() without any timeout; update the
health check (the method using redisTemplate.execute/RedisCallback) to enforce a
timeout by either configuring a connection timeout on the RedisConnectionFactory
used by redisTemplate (set the client/connection timeout property) or wrap the
execute call in a cancellable timed task (e.g., submit a
Callable/CompletableFuture that calls redisTemplate.execute(...) and use
get(timeout, unit)) and handle TimeoutException by treating Redis as unhealthy
and logging the timeout; ensure you reference redisTemplate and the
HealthService health-check method when making the change and propagate/return a
failure status on timeout.

Comment on lines +228 to +230
try {
// Run ping command to check MongoDB connectivity
Document pingResult = mongoTemplate.getDb().runCommand(new Document("ping", 1));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing timeout for MongoDB health check.

Unlike the MySQL check (which has 2s connection validation and 3s query timeout), the MongoDB ping command has no timeout. If MongoDB is unresponsive, this could cause the health endpoint to hang indefinitely.

Consider configuring a socket timeout or using MongoDB's maxTimeMS option:

♻️ Proposed fix with timeout
         try {
             // Run ping command to check MongoDB connectivity
-            Document pingResult = mongoTemplate.getDb().runCommand(new Document("ping", 1));
+            Document pingCommand = new Document("ping", 1)
+                .append("maxTimeMS", 3000); // 3 second timeout
+            Document pingResult = mongoTemplate.getDb().runCommand(pingCommand);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
// Run ping command to check MongoDB connectivity
Document pingResult = mongoTemplate.getDb().runCommand(new Document("ping", 1));
try {
// Run ping command to check MongoDB connectivity
Document pingCommand = new Document("ping", 1)
.append("maxTimeMS", 3000); // 3 second timeout
Document pingResult = mongoTemplate.getDb().runCommand(pingCommand);
🤖 Prompt for AI Agents
In @src/main/java/com/iemr/admin/service/health/HealthService.java around lines
228 - 230, The MongoDB ping in HealthService
(mongoTemplate.getDb().runCommand(...)) lacks a timeout and can hang; add a
timeout by either supplying a maxTimeMS to the ping command (e.g., include a
maxTimeMS value in the Document/BSON passed to runCommand) or configure the
MongoClient's socket/timeout settings (MongoClientSettings socketTimeout or
serverSelectionTimeout) used by mongoTemplate; update the runCommand invocation
or the MongoClient configuration so the health check uses a bounded timeout
(e.g., 2–3s) to mirror the MySQL check.

Comment on lines +230 to +232
Document pingResult = mongoTemplate.getDb().runCommand(new Document("ping", 1));

if (pingResult != null && pingResult.getDouble("ok") == 1.0) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Potential NullPointerException on MongoDB ping result check.

pingResult.getDouble("ok") returns null if the key doesn't exist, and comparing with == 1.0 will cause auto-unboxing NPE.

🐛 Proposed fix
-            if (pingResult != null && pingResult.getDouble("ok") == 1.0) {
+            if (pingResult != null && Double.valueOf(1.0).equals(pingResult.getDouble("ok"))) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Document pingResult = mongoTemplate.getDb().runCommand(new Document("ping", 1));
if (pingResult != null && pingResult.getDouble("ok") == 1.0) {
Document pingResult = mongoTemplate.getDb().runCommand(new Document("ping", 1));
if (pingResult != null && Double.valueOf(1.0).equals(pingResult.getDouble("ok"))) {
🤖 Prompt for AI Agents
In @src/main/java/com/iemr/admin/service/health/HealthService.java around lines
230 - 232, The pingResult null-check is incomplete and calling
pingResult.getDouble("ok") can return null and cause an NPE; change the check to
safely retrieve and verify the "ok" field (for example: use pingResult.get("ok",
Number.class) or pingResult.get("ok", Double.class'), ensure the returned value
is non-null, then call .doubleValue() and compare to 1.0), e.g., obtain Number
ok = pingResult.get("ok", Number.class); and use if (pingResult != null && ok !=
null && ok.doubleValue() == 1.0) to avoid auto-unboxing NPE in the HealthService
ping logic that calls mongoTemplate.getDb().runCommand.

Comment on lines +77 to +81

## MongoDB Configuration
spring.data.mongodb.host=mongodb-container
spring.data.mongodb.port=27017
spring.data.mongodb.database=amrit
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing MongoDB authentication configuration.

The MongoDB configuration lacks authentication properties (spring.data.mongodb.username, spring.data.mongodb.password). While this may work for local development, production deployments should use authenticated connections.

Consider adding authentication and optionally TLS configuration:

spring.data.mongodb.username=${MONGO_USER}
spring.data.mongodb.password=${MONGO_PASSWORD}
spring.data.mongodb.authentication-database=admin
# Optional: Enable TLS for production
# spring.data.mongodb.ssl.enabled=true
🤖 Prompt for AI Agents
In @src/main/resources/application.properties around lines 77 - 81, Add MongoDB
authentication properties to the existing spring.data.mongodb.* configuration:
include spring.data.mongodb.username and spring.data.mongodb.password (sourced
from environment variables like MONGO_USER/MONGO_PASSWORD), set
spring.data.mongodb.authentication-database (e.g., admin), and optionally enable
TLS with spring.data.mongodb.ssl.enabled=true for production; ensure credentials
are injected via external config or secrets manager (do not hardcode) and update
any connection-handling code to use these properties.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
17.8% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@Suraj-kumar00 Suraj-kumar00 closed this by deleting the head repository Jan 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant