Skip to content

Conversation

@vaishnavbhosale
Copy link

@vaishnavbhosale vaishnavbhosale commented Jan 7, 2026

📋 Description

JIRA ID: N/A

This PR implements standardized /health and /version endpoints in the Common-API as part of Issue #102.

  • Added a lightweight /health endpoint returning service status.
  • Refactored the existing /version endpoint to return a consistent JSON response containing:
  • Git commit hash
  • Build timestamp (from git.properties)
  • Ensured new classes include GPLv3 license headers and proper Javadocs.
  • These changes improve observability, maintainability, and deployment traceability without impacting existing functionality.

✅ 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

Testing:

  • The project builds successfully using mvn clean install.
  • Endpoints are lightweight and do not require database connectivity.
  • No existing routes or configurations were modified.

Notes:

Summary by CodeRabbit

  • New Features

    • Added a /health endpoint reporting overall status and per-component health for database and Redis; components may be marked NOT_CONFIGURED when not present. Responds 200 when UP or 503 when degraded.
    • Version endpoint now exposes structured build info (commit hash and build time).
  • Refactor

    • Version endpoint response changed from a plain string to a typed object.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

Adds a HealthController exposing GET /health that reports overall status and per-component (database, redis) states; refactors VersionController to return a new VersionInfo DTO (commitHash, buildTime) loaded from git.properties.

Changes

Cohort / File(s) Summary
Health Endpoint
src/main/java/com/iemr/common/controller/health/HealthController.java
New Spring REST controller exposing GET /health. Produces a response with top-level "status" and a "components" map. If DataSource/RedisConnectionFactory are configured performs connection checks (DB query, Redis PING) marking each "UP", "DOWN", or "NOT_CONFIGURED". Overall status is UP only if both checks succeed; returns 200 when UP, 503 when DOWN; logs failures.
Version Endpoint & DTO
src/main/java/com/iemr/common/controller/version/VersionController.java, src/main/java/com/iemr/common/controller/version/VersionInfo.java
VersionController now returns VersionInfo instead of String. Loads git.properties via try-with-resources with null-check and error logging. Adds VersionInfo DTO with commitHash and buildTime and corresponding getters; public API signature changed.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant HealthController
  participant Database
  participant Redis
  Client->>HealthController: GET /health
  HealthController->>HealthController: init components map
  alt DataSource configured
    HealthController->>Database: open connection & run test query
    Database-->>HealthController: success / exception
  else DataSource not configured
    HealthController-->>HealthController: mark database NOT_CONFIGURED
  end
  alt Redis configured
    HealthController->>Redis: open connection & PING
    Redis-->>HealthController: PONG / error
  else Redis not configured
    HealthController-->>HealthController: mark redis NOT_CONFIGURED
  end
  HealthController->>HealthController: compute overall status (UP/DOWN)
  alt overall UP
    HealthController-->>Client: 200 OK + body
  else overall DOWN
    HealthController-->>Client: 503 Service Unavailable + body
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 I hop and check each service near and far,

Ping Redis quick, open DB jar.
Git commit and build time tucked in a line,
I return the status, green or red sign. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 accurately summarizes the two main changes: adding a new /health endpoint and refactoring the /version endpoint to return standardized JSON response with commit hash and build timestamp.

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

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13db52a and 49edb56.

📒 Files selected for processing (1)
  • src/main/java/com/iemr/common/controller/health/HealthController.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/iemr/common/controller/health/HealthController.java

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
Contributor

@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: 0

🧹 Nitpick comments (6)
src/main/java/com/iemr/common/controller/health/HealthController.java (2)

22-27: Javadoc placement before package declaration is non-standard.

In Java, the class-level Javadoc should appear after imports and immediately before the class definition, not before the package statement.

🔎 Suggested fix
 * along with this program. If not, see https://www.gnu.org/licenses/.
 */
-/**
- * Health check controller for Common-API.
- *
- * @author vaishnavbhosale
- */
 package com.iemr.common.controller.health;

 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 import java.util.Map;

+/**
+ * Health check controller for Common-API.
+ *
+ * @author vaishnavbhosale
+ */
 @RestController
 public class HealthController {

33-40: Consider adding @Operation annotation for API documentation consistency.

The VersionController uses @Operation(summary = "Get version") for Swagger documentation. For consistency across endpoints, consider adding similar documentation here.

🔎 Suggested fix
+import io.swagger.v3.oas.annotations.Operation;
+
 @RestController
 public class HealthController {

+    @Operation(summary = "Health check")
     @GetMapping("/health")
     public Map<String, String> health() {
         return Map.of("status", "UP");
     }
 }
src/main/java/com/iemr/common/controller/version/VersionController.java (2)

22-31: Javadoc placement before package declaration is non-standard.

Same as in HealthController, the Javadoc should appear after imports and before the class definition.


56-66: Consider logging when git.properties is missing.

If git.properties is absent (e.g., running from IDE without a build), the code silently returns defaults. A debug/warn log would help diagnose why version info shows "unknown".

🔎 Suggested improvement
 		try (InputStream is = getClass()
 				.getClassLoader()
 				.getResourceAsStream("git.properties")) {

 			if (is != null) {
 				properties.load(is);
+			} else {
+				logger.warn("git.properties not found on classpath");
 			}

 		} catch (Exception e) {
 			logger.error("Error reading git.properties", e);
 		}
src/main/java/com/iemr/common/controller/version/VersionInfo.java (2)

22-27: Javadoc placement before package declaration is non-standard.

Same as the other files - move Javadoc after imports and before the class definition.


29-46: Consider making fields final for true immutability.

Since this is a DTO with only getters, marking the fields as final clearly communicates immutability and prevents accidental modification.

🔎 Suggested fix
 public class VersionInfo {

-    private String commitHash;
-    private String buildTime;
+    private final String commitHash;
+    private final String buildTime;

     public VersionInfo(String commitHash, String buildTime) {
         this.commitHash = commitHash;
         this.buildTime = buildTime;
     }

Alternatively, given the project targets Java 17 and already uses records extensively, this could be simplified to a record:

public record VersionInfo(String commitHash, String buildTime) {}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ffa450 and 2a3678c.

📒 Files selected for processing (3)
  • src/main/java/com/iemr/common/controller/health/HealthController.java
  • src/main/java/com/iemr/common/controller/version/VersionController.java
  • src/main/java/com/iemr/common/controller/version/VersionInfo.java
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2024-12-07T19:32:42.660Z
Learnt from: helenKaryamsetty
Repo: PSMRI/Common-API PR: 123
File: src/main/java/com/iemr/common/controller/abdmfacility/AbdmFacilityController.java:31-31
Timestamp: 2024-12-07T19:32:42.660Z
Learning: In this codebase, for Java Spring Boot API controllers like `AbdmFacilityController.java`, it's a common pattern to include the `Authorization` parameter in method signatures, even if it's not used in the implementation, to maintain consistency across APIs.

Applied to files:

  • src/main/java/com/iemr/common/controller/health/HealthController.java
🧬 Code graph analysis (1)
src/main/java/com/iemr/common/controller/health/HealthController.java (1)
src/main/java/com/iemr/common/controller/version/VersionController.java (1)
  • RestController (44-73)
🔇 Additional comments (1)
src/main/java/com/iemr/common/controller/version/VersionController.java (1)

52-71: Implementation looks correct and handles edge cases well.

Good use of try-with-resources for automatic resource cleanup, proper null checking, and sensible default values when properties are unavailable. The refactoring to return VersionInfo instead of a String provides a cleaner API contract.

Copy link
Contributor

@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: 3

🤖 Fix all issues with AI agents
In @src/main/java/com/iemr/common/controller/health/HealthController.java:
- Around line 85-99: The catch block in checkRedis currently swallows
exceptions; update checkRedis (which uses redisConnectionFactory and
RedisConnection) to log the exception when connectivity fails: in the
catch(Exception e) for checkRedis, call the controller's logger (e.g.,
logger.error or LOG.error) with a descriptive message like "Redis connectivity
check failed" and include the exception e so the stacktrace/error details are
recorded, then continue to set components.put("redis","DOWN") and return false.
- Around line 55-68: The health() method currently always returns 200; modify
HealthController.health() to return a ResponseEntity<Map<String,Object>> instead
of raw Map so you can set the HTTP status based on the computed health: call
checkDatabase(components) and checkRedis(components) as before, build the
response map with "status" and "components", then return
ResponseEntity.ok(response) when both are UP and
ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(response) when either
is DOWN; ensure imports for ResponseEntity and HttpStatus are added and
references to health(), checkDatabase(), and checkRedis() are preserved.
- Around line 70-83: The checkDatabase method currently swallows exceptions;
update the catch block in checkDatabase to log the failure (use the class logger
at WARN or ERROR level) including the exception message and stacktrace and the
components map entry for "database" before returning false. While here, after
obtaining the Connection from dataSource in checkDatabase, optionally run a
lightweight validation query (e.g., "SELECT 1") via
connection.createStatement()/executeQuery() and only mark "database" as "UP" if
the query succeeds; on any SQLException log the error and set
components.put("database","DOWN").
🧹 Nitpick comments (1)
src/main/java/com/iemr/common/controller/health/HealthController.java (1)

23-32: Consider moving Javadoc to class-level or package-info.java.

Package-level Javadoc before the package statement is non-standard. Most tools and conventions expect:

  • Package documentation in a separate package-info.java file, or
  • Class documentation directly above the class declaration

Moving this to a class-level Javadoc would improve clarity and tool compatibility.

♻️ Suggested refactor

Move the Javadoc to just above the class:

-/**
- * Health check controller for Common-API.
- * <p>
- * Verifies application liveness and connectivity to underlying
- * runtime dependencies such as Database and Redis.
- * </p>
- *
- * @author vaishnavbhosale
- */
 package com.iemr.common.controller.health;
 
 import java.sql.Connection;
 import java.util.HashMap;
 import java.util.Map;
 
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.connection.RedisConnection;
 import org.springframework.data.redis.connection.RedisConnectionFactory;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+/**
+ * Health check controller for Common-API.
+ * <p>
+ * Verifies application liveness and connectivity to underlying
+ * runtime dependencies such as Database and Redis.
+ * </p>
+ *
+ * @author vaishnavbhosale
+ */
 @RestController
 public class HealthController {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a3678c and 4c01959.

📒 Files selected for processing (1)
  • src/main/java/com/iemr/common/controller/health/HealthController.java
🔇 Additional comments (2)
src/main/java/com/iemr/common/controller/health/HealthController.java (2)

1-21: License header is properly formatted.

The GPLv3 license header is complete and follows standard conventions.


46-53: Appropriate use of optional dependencies.

Using @Autowired(required = false) for DataSource and RedisConnectionFactory correctly handles environments where these dependencies might not be configured.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 8, 2026

@vaishnavbhosale
Copy link
Author

Hi @drtechie ,

I’ve updated the Common-API /health and /version implementation based on the review feedback.

Changes completed:

  • /health now checks underlying dependencies (Database and Redis)
  • Added a DB validation query (SELECT 1) to verify query execution
  • Returns HTTP 503 when any critical dependency is DOWN
  • Added proper error logging for DB and Redis failures
  • Refactored to constructor-based dependency injection
  • Introduced constants for component keys to align with clean-code practices

All CI workflows and SonarCloud checks are passing.

Please let me know if you’d like me to apply the same pattern to other AMRIT API repositories or make any further refinements.

Thanks!
Vaishnav

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