Skip to content

Conversation

@srishtigrp78
Copy link
Contributor

@srishtigrp78 srishtigrp78 commented Apr 3, 2025

πŸ“‹ 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

  • Chores
    • Introduced enhanced logging to improve the monitoring and diagnosis of key data operations across multiple services, including NCD Care, ANC, Cancer Screening, COVID-19, General OPD, NCD Screening, and PNC. This includes logging success and error messages for various save operations, enhancing traceability and error handling.
    • Updated JWT handling to a new parsing and verification approach, added token denylist validation to improve security by preventing use of revoked tokens.
    • Added a new token denylist management component using Redis to support token revocation and enhance authentication control.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 3, 2025

Walkthrough

The changes introduce logging functionality across multiple service implementations, enhancing the traceability of operations in methods responsible for saving various healthcare data. A Logger instance is created using LoggerFactory, initialized with the class name, and utilized to log messages indicating the start and success or failure of save operations. This includes detailed logging for history, vital, examination, and other domain-specific details in respective service classes, thereby improving error handling and monitoring capabilities. Additionally, JWT token parsing was updated to a new API with denylist validation, and a new TokenDenylist component was added to manage token denylisting using Redis.

Changes

File Path Change Summary
src/main/java/com/iemr/tm/service/ncdCare/NCDCareServiceImpl.java Added a Logger instance and inserted logging statements for saving operations in saveNCDCareNurseData.
src/main/java/com/iemr/tm/service/anc/ANCServiceImpl.java Added a Logger instance and logging for saving operations in saveANCNurseData.
src/main/java/com/iemr/tm/service/cancerScreening/CSServiceImpl.java Added logging for saving operations in saveCancerScreeningNurseData, including history, examination, and vitals details.
src/main/java/com/iemr/tm/service/covid19/Covid19ServiceImpl.java Added a Logger instance and logging for saving operations in saveCovid19NurseData.
src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java Added a Logger instance and logging for saving operations in saveNurseData. Added string constants for JSON keys.
src/main/java/com/iemr/tm/service/ncdscreening/NCDScreeningServiceImpl.java Added a Logger instance and logging for saving operations in saveNCDScreeningNurseData.
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java Added a Logger instance and logging for saving operations in savePNCNurseData. Added string constants for JSON keys.
src/main/java/com/iemr/tm/utils/JwtUtil.java Updated JWT parsing and verification to new API style; changed getSigningKey() to return SecretKey; added token denylist validation; improved null safety in claim extraction.
src/main/java/com/iemr/tm/utils/TokenDenylist.java Added new TokenDenylist Spring component managing token denylist in Redis with methods to add tokens and check denylist status.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ServiceImpl
    participant Logger
    participant HistoryHandler
    participant VitalHandler
    participant ExaminationHandler

    Client->>ServiceImpl: call saveNurseData()
    ServiceImpl->>Logger: log "Starting save of HistoryDetails"
    ServiceImpl->>HistoryHandler: save HistoryDetails
    HistoryHandler-->>ServiceImpl: return success flag
    ServiceImpl->>Logger: log success or error for HistoryDetails

    ServiceImpl->>Logger: log "Starting save of VitalDetails"
    ServiceImpl->>VitalHandler: save VitalDetails
    VitalHandler-->>ServiceImpl: return success flag
    ServiceImpl->>Logger: log success or error for VitalDetails

    ServiceImpl->>Logger: log "Starting save of ExaminationDetails"
    ServiceImpl->>ExaminationHandler: save ExaminationDetails
    ExaminationHandler-->>ServiceImpl: return success flag
    ServiceImpl->>Logger: log success or error for ExaminationDetails
Loading

Poem

I’m a happy rabbit with a logging song,
Hoping through code all day long.
Each save logs a tale of success or error,
Tracing each step without a whisper of terror.
My leafy ears twitch at each debug delight,
Celebrating changes from morning to night!
πŸ‡βœ¨

✨ Finishing Touches
  • πŸ“ Generate Docstrings

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
πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 2

πŸ”­ Outside diff range comments (1)
src/main/java/com/iemr/tm/service/ncdCare/NCDCareServiceImpl.java (1)

129-236: πŸ› οΈ Refactor suggestion

Add debug logging for resolving multiple visits issue.

Based on the PR title "Digwal_TM multiple visit in db for single beneficiary", you should consider adding more detailed logging in the visit creation/validation logic to help diagnose and track the issue of duplicate visits. The current logging only covers history and vital saving operations but doesn't directly address the multiple visit problem mentioned in the PR title.

Add appropriate logging in the visit creation section (around lines 138-154) to track when visits are created vs when they already exist:

 Map<String, Long> visitIdAndCodeMap = saveBenVisitDetails(requestOBJ.getAsJsonObject("visitDetails"),
         nurseUtilityClass);

+logger.debug("Attempting to create or retrieve visit for beneficiary ID: {}", nurseUtilityClass.getBeneficiaryRegID());
 if (visitIdAndCodeMap != null && visitIdAndCodeMap.size() > 0 && visitIdAndCodeMap.containsKey("visitID")
         && visitIdAndCodeMap.containsKey("visitCode")) {
     benVisitID = visitIdAndCodeMap.get("visitID");
     benVisitCode = visitIdAndCodeMap.get("visitCode");

+    logger.info("Using visit with ID: {} and code: {} for beneficiary ID: {}", 
+        benVisitID, benVisitCode, nurseUtilityClass.getBeneficiaryRegID());
     nurseUtilityClass.setVisitCode(benVisitCode);
     nurseUtilityClass.setBenVisitID(benVisitID);
 }else {
+    logger.info("Data already exists for beneficiary ID: {}, skipping new visit creation", 
+        nurseUtilityClass.getBeneficiaryRegID());
     Map<String, String> responseMap = new HashMap<String, String>();
     responseMap.put("response", "Data already saved");
     return new Gson().toJson(responseMap);
 }

Also, consider adding logging in the saveBenVisitDetails method (around line 315) where the code checks for existing data:

 int i=commonNurseServiceImpl.getMaxCurrentdate(benVisitDetailsOBJ.getBeneficiaryRegID(),benVisitDetailsOBJ.getVisitReason(),benVisitDetailsOBJ.getVisitCategory());
+logger.debug("getMaxCurrentdate check result for benID {}: {}", benVisitDetailsOBJ.getBeneficiaryRegID(), i);
 if(i<1) {
+    logger.info("Creating new visit for beneficiary ID: {}", benVisitDetailsOBJ.getBeneficiaryRegID());
 benVisitID = commonNurseServiceImpl.saveBeneficiaryVisitDetails(benVisitDetailsOBJ);
🧹 Nitpick comments (3)
src/main/java/com/iemr/tm/service/ncdCare/NCDCareServiceImpl.java (3)

83-83: Consider using fully qualified class name for logger.

The logger is initialized with the simple class name, which works but using the fully qualified class name is generally considered a better practice for more precise logging.

-private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+private Logger logger = LoggerFactory.getLogger(this.getClass());

172-172: Use parameterized logging instead of string concatenation.

String concatenation in logging statements is less efficient than using parameterized logging, especially in high-volume scenarios.

-logger.info("start saving BenNCDCareHistoryDetails for BenVisitID"+ benVisitID + "and" + benVisitCode);
+logger.info("start saving BenNCDCareHistoryDetails for BenVisitID {} and {}", benVisitID, benVisitCode);

182-182: Use parameterized logging instead of string concatenation.

String concatenation in logging statements is less efficient than using parameterized logging, especially in high-volume scenarios.

-logger.info("start saving BenNCDCareVitalDetails for BenVisitID"+ benVisitID + "and" + benVisitCode);
+logger.info("start saving BenNCDCareVitalDetails for BenVisitID {} and {}", benVisitID, benVisitCode);
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 2055298 and fe0ba2d.

πŸ“’ Files selected for processing (1)
  • src/main/java/com/iemr/tm/service/ncdCare/NCDCareServiceImpl.java (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (1)
src/main/java/com/iemr/tm/service/ncdCare/NCDCareServiceImpl.java (1)

32-33: Appropriate SLF4J logging import.

The imports for SLF4J logging framework are necessary for the implemented logging functionality.

Copy link
Contributor

@ravishanigarapu ravishanigarapu left a comment

Choose a reason for hiding this comment

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

@srishtigrp78 Its seems like you have only added loggers.are these loggers really necessary to commit.

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: 1

πŸ”­ Outside diff range comments (4)
src/main/java/com/iemr/tm/service/covid19/Covid19ServiceImpl.java (2)

108-223: πŸ› οΈ Refactor suggestion

Consider implementing consistent try-catch with logging for better error handling.

The method contains multiple operations that could throw exceptions, but lacks comprehensive exception handling with detailed logging.

Consider implementing try-catch blocks around critical operations with appropriate logging of exceptions:

 try {
     // existing code for saving history details
     historySaveSuccessFlag = saveBenCovid19HistoryDetails(requestOBJ.getAsJsonObject("historyDetails"),
                                                           benVisitID, benVisitCode);
 } catch (Exception e) {
     logger.error("Exception occurred while saving Covid19 history details: {}", e.getMessage(), e);
     throw e;
 }

This would provide much better diagnostic information in production environments.


980-1183: πŸ› οΈ Refactor suggestion

Add logging to doctor data operations for consistency.

Logging has been added to nurse operations, but the doctor-related methods (saveDoctorData, getBenCaseRecordFromDoctorCovid19, etc.) lack similar logging.

For consistency, implement similar structured logging patterns in the doctor-related methods to maintain traceability throughout the application.

For example, in the saveDoctorData method:

 @Transactional(rollbackFor = Exception.class)
 public Long saveDoctorData(JsonObject requestOBJ, String Authorization) throws Exception {
+    logger.info("Start saving doctor data for beneficiary");
     Long saveSuccessFlag = null;
     // ... existing code ...
     
     // When saving findings
+    logger.info("Start saving doctor findings");
     findingSuccessFlag = commonDoctorServiceImpl.saveDocFindings(wrapperAncFindings);
+    if (findingSuccessFlag == null || findingSuccessFlag <= 0) {
+        logger.error("Error saving doctor findings");
+    } else {
+        logger.info("Successfully saved doctor findings");
+    }
     
     // Similarly for other operations
     
     // Before returning
+    if (saveSuccessFlag != null && saveSuccessFlag > 0) {
+        logger.info("Successfully completed doctor data save process");
+    } else {
+        logger.error("Failed to complete doctor data save process");
+    }
     return saveSuccessFlag;
 }
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (2)

143-143: πŸ› οΈ Refactor suggestion

Add Transaction Management to Ensure Data Consistency

The savePNCNurseData method performs multiple database operations but lacks transaction management. This could lead to partial data saves in case of failures, resulting in data inconsistency.

@Override
+@Transactional(rollbackFor = Exception.class)
public String savePNCNurseData(JsonObject requestOBJ, String Authorization) throws Exception {

Adding the @Transactional annotation ensures that all database operations within the method are executed within a single transaction, providing atomicity.


717-733: ⚠️ Potential issue

Fix Inconsistency in JSON Field Name in PNC Details Method

The method saveBenPNCDetails checks for "pNCDeatils" which has the same typo as noted earlier. This needs to be fixed to maintain consistency.

-if (pncDetailsOBJ != null && pncDetailsOBJ.has("pNCDeatils") && !pncDetailsOBJ.get("pNCDeatils").isJsonNull()) {
-    // Save Ben PNC Care Details
-    PNCCare pncCareDetailsOBJ = InputMapper.gson().fromJson(pncDetailsOBJ.get("pNCDeatils"), PNCCare.class);
+if (pncDetailsOBJ != null && pncDetailsOBJ.has("pNCDetails") && !pncDetailsOBJ.get("pNCDetails").isJsonNull()) {
+    // Save Ben PNC Care Details
+    PNCCare pncCareDetailsOBJ = InputMapper.gson().fromJson(pncDetailsOBJ.get("pNCDetails"), PNCCare.class);
🧹 Nitpick comments (19)
src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (4)

154-161: Good use of parameterized logging with appropriate context

The logging implementation correctly:

  • Uses parameterized logging with {} placeholders (more efficient than string concatenation)
  • Includes relevant context (benVisitID and benVisitCode)
  • Uses appropriate log levels (info for normal operation, error for errors)

Consider enhancing error logging by also capturing any exceptions that might be thrown:

if (historySaveSuccessFlag == null || historySaveSuccessFlag <= 0) {
-    logger.error("Error in saving BenGeneralOPDHistoryDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
+    logger.error("Error in saving BenGeneralOPDHistoryDetails for BenVisitID={} and BenVisitCode={}. Details: save operation returned {}", benVisitID, benVisitCode, historySaveSuccessFlag);
}

178-185: Comprehensive logging for examination details

The logging statements provide good visibility into the examination details save process.

There's a minor inconsistency in indentation of the logging blocks compared to other similar blocks. Consider standardizing the indentation across all logging sections for better readability.


290-317: Consider adding logging for duplicate visit detection

This code section prevents duplicate entries by checking getMaxCurrentdate(), which aligns with the PR's purpose of preventing multiple visits in the DB for a single beneficiary.

Consider adding logging here to track when duplicate visits are detected:

int i=commonNurseServiceImpl.getMaxCurrentdate(benVisitDetailsOBJ.getBeneficiaryRegID(),benVisitDetailsOBJ.getVisitReason(),benVisitDetailsOBJ.getVisitCategory());
if(i<1) {
+    logger.info("Creating new visit for beneficiary ID={} with reason={} and category={}", 
+        benVisitDetailsOBJ.getBeneficiaryRegID(), benVisitDetailsOBJ.getVisitReason(), benVisitDetailsOBJ.getVisitCategory());
    // existing code to save visit
+} else {
+    logger.info("Skipping creation of duplicate visit for beneficiary ID={} with reason={} and category={}", 
+        benVisitDetailsOBJ.getBeneficiaryRegID(), benVisitDetailsOBJ.getVisitReason(), benVisitDetailsOBJ.getVisitCategory());
}

760-905: Consider adding similar logging to doctor data save method

The saveDoctorData method performs similar save operations but lacks the logging improvements added to the saveNurseData method.

For consistency and better traceability, consider adding similar logging statements to this method as well, particularly for the critical operations like saving findings, prescriptions, investigations, and referrals.

Example for the findings section:

// save findings
if (requestOBJ.has("findings") && !requestOBJ.get("findings").isJsonNull()) {
+    logger.info("Start saving doctor findings for BenVisitID={} and BenVisitCode={}", 
+        commonUtilityClass.getBenVisitID(), commonUtilityClass.getVisitCode());
    WrapperAncFindings wrapperAncFindings = InputMapper.gson().fromJson(requestOBJ.get("findings"),
            WrapperAncFindings.class);
    findingSuccessFlag = commonDoctorServiceImpl.saveDocFindings(wrapperAncFindings);
+    if (findingSuccessFlag == null || findingSuccessFlag <= 0) {
+        logger.error("Error in saving doctor findings for BenVisitID={} and BenVisitCode={}", 
+            commonUtilityClass.getBenVisitID(), commonUtilityClass.getVisitCode());
+    } else {
+        logger.info("Successfully saved doctor findings for BenVisitID={} and BenVisitCode={}", 
+            commonUtilityClass.getBenVisitID(), commonUtilityClass.getVisitCode());
+    }
} else {
    findingSuccessFlag = 1;
}
src/main/java/com/iemr/tm/service/covid19/Covid19ServiceImpl.java (2)

80-81: Logger initialization follows standard pattern.

The logger is properly initialized using the class name as the logger name, which follows common logging practices.

Consider using LoggerFactory.getLogger(Covid19ServiceImpl.class) instead of this.getClass().getSimpleName() to include package information in logs for better traceability.


108-223: Consider adding additional logging for error cases.

While the added logging for history and vital details is good, the method has several other error cases that would benefit from logging:

  • Error cases in the condition blocks (e.g., line 180, 206)
  • Final response generation (lines 212-222)

Consider adding error logging for exception cases and info logging for successful completion of the entire method to provide a complete picture of the execution flow.

 } else {
+    logger.error("Error occurred while creating beneficiary visit for BeneficiaryRegID={}", nurseUtilityClass.getBeneficiaryRegID());
     throw new RuntimeException("Error occurred while creating beneficiary visit");
 }

 // At end of method, before returning
 if (null != saveSuccessFlag && saveSuccessFlag > 0) {
     responseMap.put("response", "Data saved successfully");
+    logger.info("Successfully completed Covid19 nurse data save process for BeneficiaryRegID={} with VisitCode={}", 
+               nurseUtilityClass.getBeneficiaryRegID(), benVisitCode);
 } else {
     responseMap.put("response", "Unable to save data");
+    logger.error("Failed to complete Covid19 nurse data save process for BeneficiaryRegID={}", 
+                nurseUtilityClass.getBeneficiaryRegID());
 }
src/main/java/com/iemr/tm/service/anc/ANCServiceImpl.java (5)

105-105: Consider using fully qualified class name for logger.

While using getSimpleName() works, using the fully qualified class name is a better practice for easier identification in log files.

-private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+private Logger logger = LoggerFactory.getLogger(this.getClass());

170-171: Add entry logging for the main method.

For better traceability, consider adding a log entry at the beginning of the saveANCNurseData method.

@Override
public String saveANCNurseData(JsonObject requestOBJ, String Authorization) throws Exception {
+	logger.info("Entering saveANCNurseData method for beneficiary");
	// String vr = "";
	Long saveSuccessFlag = null;

299-300: Add exit logging for the main method.

For complete traceability, add a log message at the end of the method showing the final outcome.

	}
+	logger.info("Exiting saveANCNurseData method with status: {}", saveSuccessFlag != null && saveSuccessFlag > 0 ? "Success" : "Failure");
	return new Gson().toJson(responseMap);			
}

1500-1502: Consider adding logging to updateANCDoctorData method.

For consistency, consider adding similar logging patterns to other major methods like updateANCDoctorData.

@Transactional(rollbackFor = Exception.class)
public Long updateANCDoctorData(JsonObject requestOBJ, String Authorization) throws Exception {
+	logger.info("Entering updateANCDoctorData method");
	Long updateSuccessFlag = null;

105-107: Consider using MDC for enhanced logging.

For more sophisticated logging, consider implementing Mapped Diagnostic Context (MDC) to correlate logs across method calls, especially in high-volume environments.

private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());

+/**
+ * Sets MDC context for logging
+ * 
+ * @param benRegID Beneficiary registration ID
+ * @param visitCode Visit code
+ */
+private void setLogContext(Long benRegID, Long visitCode) {
+    MDC.put("benRegID", benRegID != null ? benRegID.toString() : "NA");
+    MDC.put("visitCode", visitCode != null ? visitCode.toString() : "NA");
+}
+
+/**
+ * Clears MDC context
+ */
+private void clearLogContext() {
+    MDC.clear();
+}
src/main/java/com/iemr/tm/service/ncdscreening/NCDScreeningServiceImpl.java (5)

86-87: Consider using the fully qualified class name for logger.

While using getSimpleName() works, using this.getClass() would provide the fully qualified class name in logs, which is more helpful for troubleshooting in large applications.

-private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());
+private Logger logger = LoggerFactory.getLogger(this.getClass());

196-198: Missing logging for history details save operation.

For consistency, consider adding similar logging statements for the history details save operation, following the same pattern used for other operations.

// call method to save History data
if (requestOBJ.has("historyDetails") && !requestOBJ.get("historyDetails").isJsonNull())
+    logger.info("Start saving BenNCDCareHistoryDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
    historySaveSuccessFlag = saveBenNCDCareHistoryDetails(requestOBJ.getAsJsonObject("historyDetails"),
            benVisitID, benVisitCode);
+if (historySaveSuccessFlag == null || historySaveSuccessFlag <= 0) {
+    logger.error("Error in saving BenNCDCareHistoryDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
+} else {
+    logger.info("Successfully saved BenNCDCareHistoryDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
+}

155-178: Consider adding logging for visit details operations.

The visit details saving operation at the beginning of the method would benefit from similar logging statements to enhance traceability.

// check if visit details data is not null
if (requestOBJ != null && requestOBJ.has("visitDetails") && !requestOBJ.get("visitDetails").isJsonNull()) {
    CommonUtilityClass nurseUtilityClass = InputMapper.gson().fromJson(requestOBJ, CommonUtilityClass.class);
    // Call method to save visit details data
+    logger.info("Start saving beneficiary visit details");
    Map<String, Long> visitIdAndCodeMap = saveBenVisitDetails(requestOBJ.getAsJsonObject("visitDetails"),
            nurseUtilityClass);

    // 07-06-2018 visit code
    Long benVisitID = null;

    if (visitIdAndCodeMap != null && visitIdAndCodeMap.size() > 0 && visitIdAndCodeMap.containsKey("visitID")
            && visitIdAndCodeMap.containsKey("visitCode")) {
        benVisitID = visitIdAndCodeMap.get("visitID");
        benVisitCode = visitIdAndCodeMap.get("visitCode");

        nurseUtilityClass.setVisitCode(benVisitCode);
        nurseUtilityClass.setBenVisitID(benVisitID);
+        logger.info("Successfully saved beneficiary visit details with visitID={} and visitCode={}", benVisitID, benVisitCode);
    } else {
+        logger.info("Beneficiary visit details already exist");
        Map<String, String> responseMap = new HashMap<String, String>();
        responseMap.put("response", "Data already saved");
        return new Gson().toJson(responseMap);
    }

229-254: Consider adding logging for final status of the operation.

Adding logging statements at the end of the method would provide better visibility into the overall success or failure of the operation.

if ((null != historySaveSuccessFlag && historySaveSuccessFlag > 0)
        && (null != vitalSaveSuccessFlag && vitalSaveSuccessFlag > 0)) {

    /**
     * We have to write new code to update ben status flow new logic
     */
+    logger.info("Starting to update beneficiary flow status after nurse activity");
    int J = updateBenFlowNurseAfterNurseActivityANC(tmpOBJ, benVisitID, benFlowID, benVisitCode,
            nurseUtilityClass.getVanID(), tcRequestOBJ);

    if (J > 0)
        saveSuccessFlag = historySaveSuccessFlag;
    else {
+        logger.error("Failed to update beneficiary flow status");
        throw new RuntimeException("Error occurred while saving data. Beneficiary status update failed");
    }

    if (J > 0 && tcRequestOBJ != null && tcRequestOBJ.getWalkIn() == false) {
+        logger.info("Sending SMS notification for scheduled appointment");
        int k = sMSGatewayServiceImpl.smsSenderGateway("schedule", nurseUtilityClass.getBeneficiaryRegID(),
                tcRequestOBJ.getSpecializationID(), tcRequestOBJ.getTmRequestID(), null,
                nurseUtilityClass.getCreatedBy(),
                tcRequestOBJ.getAllocationDate() != null ? String.valueOf(tcRequestOBJ.getAllocationDate())
                        : "",
                null, Authorization);
+        logger.info("SMS notification status: {}", k > 0 ? "Sent successfully" : "Failed to send");
    }

} else {
+    logger.error("Error in saving nurse data - either history or vital details failed to save");
    throw new RuntimeException("Error occurred while saving data");
}

262-266: Add logging before returning the final response.

For complete end-to-end traceability, consider adding logging before returning the final response.

if (null != saveSuccessFlag && saveSuccessFlag > 0) {
    responseMap.put("response", "Data saved successfully");
+    logger.info("NCD Screening nurse data saved successfully with visitCode={}", benVisitCode);
} else {
    responseMap.put("response", "Unable to save data");
+    logger.error("Failed to save NCD Screening nurse data with visitCode={}", benVisitCode);
}
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (3)

143-280: Consider Refactoring Large Method

The savePNCNurseData method is quite large (over 130 lines) and handles multiple responsibilities, making it difficult to maintain and understand. Consider breaking it down into smaller, focused methods for better maintainability.

For example, you could extract separate methods for:

  1. Processing and validating the request
  2. Handling visit details
  3. Coordinating the save operations
  4. Processing the results and generating the response

This would make the code more modular and easier to test and maintain.


143-280: Enhance Error Handling with More Context

While the added logging improves traceability, the error handling could be enhanced by providing more detailed exception messages and implementing a custom exception class for domain-specific errors.

For example, instead of:

throw new RuntimeException("Error occurred while saving data");

Consider:

throw new PNCDataSaveException("Failed to save PNC data for beneficiary ID: " + nurseUtilityClass.getBeneficiaryRegID() 
    + ", visit code: " + benVisitCode + ". Details: history=" + (historySaveSuccessFlag != null) 
    + ", pnc=" + (pncSaveSuccessFlag != null) + ", vitals=" + (vitalSaveSuccessFlag != null) 
    + ", exam=" + (examtnSaveSuccessFlag != null));

This would provide much more context for troubleshooting.


143-280: Enhance Logging with User Context

Consider enhancing the logging by including user or session information to make troubleshooting easier in a production environment with multiple concurrent users.

For example:

-logger.info("Start saving BenPNCHistoryDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
+logger.info("User {} - Start saving BenPNCHistoryDetails for BenVisitID={} and BenVisitCode={}", 
+    nurseUtilityClass.getCreatedBy(), benVisitID, benVisitCode);

This additional context can be very valuable when debugging issues in logs with entries from multiple users.

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d1ca734 and 5f4c042.

πŸ“’ Files selected for processing (6)
  • src/main/java/com/iemr/tm/service/anc/ANCServiceImpl.java (3 hunks)
  • src/main/java/com/iemr/tm/service/cancerScreening/CSServiceImpl.java (1 hunks)
  • src/main/java/com/iemr/tm/service/covid19/Covid19ServiceImpl.java (3 hunks)
  • src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (3 hunks)
  • src/main/java/com/iemr/tm/service/ncdscreening/NCDScreeningServiceImpl.java (3 hunks)
  • src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (26)
src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (3)

31-32: LGTM: Good choice using SLF4J for logging

Adding SLF4J imports for logging functionality is appropriate as it provides a flexible logging API that works with multiple logging implementations.


86-86: Well-structured logger initialization

Using the class name as the logger name is a good practice as it enables filtering logs by class and makes log output more readable.


166-173: Consistent logging approach for vital details

Good implementation of logging before and after the vital details save operation with appropriate context information.

src/main/java/com/iemr/tm/service/covid19/Covid19ServiceImpl.java (5)

32-33: Good addition of SLF4J logging framework.

The inclusion of SLF4J logging dependencies is a good practice, allowing for flexible logging implementations.


161-168: Good implementation of structured logging for history data processing.

The logging implementation:

  1. Uses parameterized logging with placeholders ({}) instead of string concatenation
  2. Includes contextual information (benVisitID and benVisitCode)
  3. Uses appropriate log levels (info for normal flow, error for failures)
  4. Logs at the beginning of operations and after completion

This will greatly improve the traceability of operations in production.


170-177: Good implementation of structured logging for vital details processing.

Similar to the history data logging, this follows best practices with appropriate log levels, contextual information, and parameterized logging.


178-178: Empty line added for better code organization.

This subtle spacing change improves code readability by separating logical blocks.


258-269:

Details

❓ Verification inconclusive

Potential issue in saveBenVisitDetails method.

The method contains a logic block that only saves data if i < 1, but does not include any logging or error message when data is not saved due to this condition.

Verify the intention of this condition check and consider adding appropriate logging:


🏁 Script executed:

#!/bin/bash
# Find other occurrences of getMaxCurrentdate to understand its usage pattern
rg -A 2 -B 2 "getMaxCurrentdate" --type java

Length of output: 6389


Action Required: Verify Intent and Add Logging

After reviewing the usage patterns across multiple service implementations (e.g., QuickConsultation, PNC, NCDCare, NCDScreening, GeneralOPD, CancerScreening, and ANC), it appears that checking the return value of getMaxCurrentdate (i.e. if(i < 1)) to decide whether to call saveBeneficiaryVisitDetails is a consistent pattern. However, as noted, when the condition fails (i.e. i >= 1), no logging is performed to indicate that the save operation was intentionally skipped.

Please verify if the silent bypass of saving visit details is an intentional design decision. If notβ€”and to aid in debugging and improve traceabilityβ€”consider adding a log statement (for example, at DEBUG or INFO level) in the else branch to document that no new data was saved because existing data was already present.

  • File: src/main/java/com/iemr/tm/service/covid19/Covid19ServiceImpl.java (Lines 258–269)
src/main/java/com/iemr/tm/service/anc/ANCServiceImpl.java (6)

36-37: Logger setup looks good.

Appropriate import statements and logger initialization have been added. The use of SLF4J is a good choice as it provides a logging abstraction that works with various logging implementations.

Also applies to: 105-105


216-217: Good logging at the start of operations.

Adding a log message at the beginning of the ANC details saving process helps with traceability.


220-224: Proper error and success logging.

Good implementation of conditional logging that captures both successful and failed operations with meaningful context information.


226-233: Consistent logging pattern for history details.

The logging follows a consistent pattern with start, error, and success messages that include the relevant IDs.


235-243: Proper logging for vital details processing.

The implementation follows best practices by using parameterized logging with context variables.


246-253: Comprehensive logging for examination details.

The logging statements provide clear visibility into the examination details processing stage.

src/main/java/com/iemr/tm/service/ncdscreening/NCDScreeningServiceImpl.java (4)

31-32: Good addition of SLF4J logging imports.

The inclusion of SLF4J logging imports is a good practice for standardized logging implementation.


200-207: Appropriate logging for vital details operations.

Good implementation of logging with parameterized messages. The conditional logging correctly captures both success and error scenarios with relevant context information.


209-215: Good logging implementation for IDRS details.

Properly structured logging with clear start and result messages. The parameterized logging approach avoids string concatenation overhead.


217-225: Well-implemented logging for physical activity details.

The logging pattern follows a consistent approach throughout the method, making the code more maintainable and the logs easier to follow.

src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (5)

31-32: Appropriate Logger Import Added

The addition of SLF4J Logger imports is a good practice for standardized logging.


88-90: Logger Initialization Follows Best Practices

The logger is correctly initialized using the class's simple name, which is a good practice for identifying the source of log messages.


188-197: Good Logging Implementation for History Details

The logging implementation follows best practices:

  1. Logs the start of the operation
  2. Conditionally logs success or error based on the return value
  3. Includes context information (benVisitID and benVisitCode)

This enhances traceability and troubleshooting capabilities.


211-220: Well-Structured Logging for Vital Details

The logging implementation here properly tracks the start, success, and failure of the vital details saving operation, which enhances monitoring and debugging capabilities.


224-233: Effective Logging for Examination Details

The addition of logging statements here follows the same consistent pattern as in other sections, providing good traceability throughout the save operation.

src/main/java/com/iemr/tm/service/cancerScreening/CSServiceImpl.java (3)

231-237: Well-structured logging to improve traceability!

The addition of logging before and after history details saving operations enhances traceability and makes it easier to debug potential issues with beneficiary visit processing.


240-247: Good error handling with appropriate logging!

Adding conditional logging based on the examination save operation's success or failure will help track potential issues in the examination details persistence process.


249-255: Improved traceability for vitals data persistence!

The consistent logging pattern across all save operations ensures uniform traceability, making it easier to identify at which exact step an error might occur during the beneficiary visit data saving process.

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 (1)
src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (1)

158-191: Consider adding more detailed error logging in catch blocks.

While the current implementation logs errors after operation failure, it would be valuable to also log exceptions and their stack traces in catch blocks for better debugging.

Additionally, consider adding DEBUG level logging for more granular operation steps.

Example enhancement:

try {
    // existing operation code
} catch (Exception e) {
+    logger.error("Error saving BenGeneralOPDHistoryDetails for BenVisitID={} and BenVisitCode={}: {}", 
+                 benVisitID, benVisitCode, e.getMessage(), e);
}
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 172aef2 and a335523.

πŸ“’ Files selected for processing (1)
  • src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (5)
src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (5)

31-32: LGTM: Added necessary SLF4J imports for logging capability.

The addition of SLF4J Logger and LoggerFactory imports is a good practice for implementing standard logging.


86-92: Good addition of logger and constants for string literals.

The implementation follows best practices by:

  1. Creating a logger instance using the class's simple name
  2. Defining constants for string literals to improve maintainability and prevent typos

This addition enhances code readability and maintainability.


158-167: Proper implementation of logging for history details operation.

The code correctly logs:

  • The start of the operation with parameters (benVisitID, benVisitCode)
  • Success or failure status after the operation
  • Uses parameterized logging to avoid string concatenation

The use of the HISTORY_DETAILS constant instead of string literal is also a good refactoring.


170-179: Well-structured logging for vital details operation.

Similar to the history details section, this implementation follows good logging practices with:

  • Operation start information with context
  • Error or success status reporting
  • Consistent formatting

The code also properly uses the VITAL_DETAILS constant.


182-191: Consistent logging implementation for examination details operation.

The logging implementation maintains consistency with the previous sections:

  • Same logging pattern and level (info for operation start, error for failures)
  • Same contextual parameters
  • Same structural approach

Using the EXAMINATION_DETAILS constant instead of string literal maintains the code quality.

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 (1)
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (1)

229-238: Consider using a constant for "examinationDetails".

While the logging implementation is good, consider extracting "examinationDetails" into a constant like you did with the other JSON field names to maintain consistency across the class.

- private static final String PNC_DETAILS = "pNCDeatils";
- private static final String HISTORY_DETAILS = "historyDetails";
- private static final String VITAL_DETAILS = "vitalDetails";
+ private static final String PNC_DETAILS = "pNCDeatils";
+ private static final String HISTORY_DETAILS = "historyDetails";
+ private static final String VITAL_DETAILS = "vitalDetails";
+ private static final String EXAMINATION_DETAILS = "examinationDetails";

And then in the code:

- if (requestOBJ.has("examinationDetails") && !requestOBJ.get("examinationDetails").isJsonNull()) {
+ if (requestOBJ.has(EXAMINATION_DETAILS) && !requestOBJ.get(EXAMINATION_DETAILS).isJsonNull()) {
    logger.info("Start saving BenExaminationDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
-   examtnSaveSuccessFlag = saveBenExaminationDetails(requestOBJ.getAsJsonObject("examinationDetails"),
+   examtnSaveSuccessFlag = saveBenExaminationDetails(requestOBJ.getAsJsonObject(EXAMINATION_DETAILS),
        benVisitID, benVisitCode);
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between a335523 and 6925add.

πŸ“’ Files selected for processing (2)
  • src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java (3 hunks)
  • src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/iemr/tm/service/generalOPD/GeneralOPDServiceImpl.java
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (1)
Learnt from: srishtigrp78
PR: PSMRI/TM-API#66
File: src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java:200-208
Timestamp: 2025-04-03T12:46:54.443Z
Learning: The JSON field name "pNCDeatils" (instead of "pNCDetails") in PNCServiceImpl is intentionally preserved despite the typo to maintain backward compatibility with existing code.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (6)
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (6)

31-32: Good addition of logging capability.

Adding SLF4J logging framework is a good practice for tracking application flow and diagnosing issues in production.

Also applies to: 89-89


91-93: Extracted string literals into constants.

Good practice to centralize string literals as constants, improving maintainability and reducing the risk of typos.

Note: The typo in "pNCDeatils" (vs "pNCDetails") is intentionally preserved as noted in the retrieved learnings, to maintain backward compatibility with existing code.


193-202: Great addition of structured logging for history details.

The logging for history details follows best practices:

  • Parameterized logging for better performance
  • Context information (benVisitID, benVisitCode) included in messages
  • Appropriate log levels for different scenarios (info for normal operations, error for failures)
  • Clear log messages that describe the operation's start and completion status

This will significantly improve traceability and debugging capabilities.


205-213: Well-structured logging for PNC details.

The logging implementation appropriately captures the start of the operation and its outcome (success or failure), with consistent context variables.


216-225: Consistent logging for vital details.

Maintains the same logging pattern established for other operations, ensuring consistency throughout the codebase.


725-727: Good use of the PNC_DETAILS constant.

Properly uses the defined constant instead of hardcoded string literals, which is more maintainable.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Apr 3, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
16.1% Duplication on New Code (required ≀ 3%)

See analysis details on SonarQube Cloud

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 (3)
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (3)

204-205: Remove unnecessary empty line

There's an extra empty line that should be removed.

-				 
if (requestOBJ.has(PNC_DETAILS) && !requestOBJ.get(PNC_DETAILS).isJsonNull()) {

226-228: Remove unnecessary empty lines

There are multiple consecutive empty lines that should be removed for better code readability.

-				
-				
-				
// call method to save examination data

88-238: Consider refactoring repetitive logging pattern

The pattern of logging start, checking result, and logging success/error is repeated for each operation. Consider creating a helper method to reduce duplication.

+ private void logOperation(String operation, Long benVisitID, Long benVisitCode, Long resultFlag) {
+     logger.info("Start saving {} for BenVisitID={} and BenVisitCode={}", operation, benVisitID, benVisitCode);
+     
+     if (resultFlag == null || resultFlag <= 0) {
+         logger.error("Error in saving {} for BenVisitID={} and BenVisitCode={}", operation, benVisitID, benVisitCode);
+     } else {
+         logger.info("Successfully saved {} for BenVisitID={} and BenVisitCode={}", operation, benVisitID, benVisitCode);
+     }
+ }

Usage example:

if (requestOBJ.has(HISTORY_DETAILS) && !requestOBJ.get(HISTORY_DETAILS).isJsonNull()) {
    logger.info("Start saving BenPNCHistoryDetails for BenVisitID={} and BenVisitCode={}", benVisitID, benVisitCode);
    historySaveSuccessFlag = saveBenPNCHistoryDetails(requestOBJ.getAsJsonObject(HISTORY_DETAILS),
            benVisitID, benVisitCode);
    logOperation("BenPNCHistoryDetails", benVisitID, benVisitCode, historySaveSuccessFlag);
}
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between f01c2c9 and 830f3f3.

πŸ“’ Files selected for processing (1)
  • src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (1)
Learnt from: srishtigrp78
PR: PSMRI/TM-API#66
File: src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java:200-208
Timestamp: 2025-04-03T12:46:54.443Z
Learning: The JSON field name "pNCDeatils" (instead of "pNCDetails") in PNCServiceImpl is intentionally preserved despite the typo to maintain backward compatibility with existing code.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (7)
src/main/java/com/iemr/tm/service/pnc/PNCServiceImpl.java (7)

31-32: Good addition of SLF4J logging

Adding structured logging is an excellent improvement that will enhance traceability and debugging capabilities.


88-94: Well-structured logger initialization and constants

Good practice to:

  1. Initialize the logger with the class name
  2. Define constants for JSON field names to avoid hardcoded strings

Note: The spelling "pNCDeatils" (rather than "pNCDetails") is preserved intentionally for backward compatibility, as noted in the retrieved learnings.


193-202: Good implementation of structured logging for history details

The logging properly captures the start of the operation, its outcome (success/failure), and includes contextual information (benVisitID and benVisitCode) that will be valuable for troubleshooting.


205-213: Good implementation of structured logging for PNC details

The logging pattern properly tracks the operation lifecycle with relevant context parameters.


216-225: Good implementation of structured logging for vital details

The logging includes appropriate start, error, and success messages with relevant context information.


229-238: Good implementation of structured logging for examination details

The logging follows the same consistent pattern as the other sections, which is excellent for maintainability.


725-728: Good use of constant instead of hardcoded string

Using the PNC_DETAILS constant here improves code maintainability and consistency.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jun 2, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
11.3% Duplication on New Code (required ≀ 3%)

See analysis details on SonarQube Cloud

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: 1

🧹 Nitpick comments (5)
src/main/java/com/iemr/tm/utils/TokenDenylist.java (5)

26-28: Consider logging when jti is null or empty.

Silently returning when jti is invalid could hide programming errors. Consider adding a warning log to help with debugging.

 if (jti == null || jti.trim().isEmpty()) {
+    logger.warn("Attempted to denylist token with null or empty jti");
     return;
 }

35-35: Consider using a more meaningful value in Redis.

Storing a single space as the value is unconventional. Consider storing metadata that could be useful for debugging or auditing.

-redisTemplate.opsForValue().set(key, " ", expirationTime, TimeUnit.MILLISECONDS);
+redisTemplate.opsForValue().set(key, System.currentTimeMillis(), expirationTime, TimeUnit.MILLISECONDS);

36-38: Consider using a more specific exception type.

Using RuntimeException makes it harder for callers to handle specific error cases. Consider creating a custom exception or using a more specific existing exception.

 } catch (Exception e) {
-    throw new RuntimeException("Failed to denylist token", e);
+    logger.error("Failed to denylist token with jti: {}", jti, e);
+    throw new IllegalStateException("Failed to denylist token", e);
 }

50-50: Use parameterized logging instead of string concatenation.

String concatenation in logging can impact performance and is not a best practice.

-logger.error("Failed to check denylist status for jti: " + jti, e);
+logger.error("Failed to check denylist status for jti: {}", jti, e);

50-53: Document the fail-open behavior and consider security implications.

The current implementation allows potentially denylisted tokens when Redis is unavailable. This fail-open approach prioritizes availability over security. Consider if this aligns with your security requirements.

Consider adding a configuration option to control this behavior, allowing administrators to choose between fail-open (current) and fail-closed approaches based on their security requirements.

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 830f3f3 and 1e13763.

πŸ“’ Files selected for processing (2)
  • src/main/java/com/iemr/tm/utils/JwtUtil.java (4 hunks)
  • src/main/java/com/iemr/tm/utils/TokenDenylist.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/com/iemr/tm/utils/TokenDenylist.java (1)
src/main/java/com/iemr/tm/utils/JwtUtil.java (1)
  • Component (14-69)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (java)
πŸ”‡ Additional comments (4)
src/main/java/com/iemr/tm/utils/TokenDenylist.java (1)

11-23: LGTM! Well-structured component with good separation of concerns.

The class is properly annotated as a Spring component with appropriate dependency injection and follows good practices with the logger initialization and key prefix constant.

src/main/java/com/iemr/tm/utils/JwtUtil.java (3)

20-21: LGTM! TokenDenylist integration is well implemented.

The integration properly checks for denylisted tokens and handles the case where jti might not be present in the token claims.

Also applies to: 40-46


34-38: LGTM! Successful migration to the new JWT API.

The code has been properly updated to use the new JWT parsing API with the builder pattern, which is the recommended approach for newer versions of the library.

Also applies to: 63-67


59-59: LGTM! Good null safety improvement.

The null check prevents potential NullPointerException when token parsing fails.

Comment on lines 62 to 68
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
return Jwts.parser()
.verifyWith(getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

Consider adding exception handling to extractAllClaims.

The extractAllClaims method doesn't handle potential exceptions from JWT parsing, which could propagate to callers of extractClaim and extractUsername. Consider wrapping it in a try-catch block for consistency with validateToken.

 private Claims extractAllClaims(String token) {
+    try {
         return Jwts.parser()
             .verifyWith(getSigningKey())
             .build()
             .parseSignedClaims(token)
             .getPayload();
+    } catch (Exception e) {
+        return null;
+    }
 }
πŸ“ 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
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
return Jwts.parser()
.verifyWith(getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload();
}
private Claims extractAllClaims(String token) {
try {
return Jwts.parser()
.verifyWith(getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload();
} catch (Exception e) {
return null;
}
}
πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/tm/utils/JwtUtil.java around lines 62 to 68, the
extractAllClaims method lacks exception handling for JWT parsing errors. Wrap
the JWT parsing logic inside a try-catch block to catch relevant exceptions, log
or handle them appropriately, and prevent exceptions from propagating
unexpectedly to callers like extractClaim and extractUsername, ensuring
consistent error handling similar to validateToken.

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.

3 participants