Add unit tests and enhance error logging in GlobalExceptionHandler#39
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/main/java/io/github/og4dev/exception/GlobalExceptionHandler.java (2)
162-173:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winLogged status can be incorrect for registry-mapped exceptions.
The error log always prints
INTERNAL_SERVER_ERRORbefore registry lookup. For mapped exceptions (e.g., 4xx/5xx custom), logs will show the wrong status.💡 Suggested fix
- log.error("[TraceID: {}] Error in {} | Message: {} | Status: {}", - traceId, location, ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + HttpStatus resolvedStatus = HttpStatus.INTERNAL_SERVER_ERROR; + String resolvedMessage = "Internal Server Error. Please contact technical support."; // Check if the exception is registered in the ApiExceptionRegistry if (registry != null) { ApiExceptionRegistry.ExceptionRule rule = registry.getRule(ex.getClass()); if (rule != null) { - ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(rule.getStatus(), rule.getMessage()); + resolvedStatus = rule.getStatus(); + resolvedMessage = rule.getMessage(); + log.error("[TraceID: {}] Error in {} | Message: {} | Status: {}", + traceId, location, ex.getMessage(), resolvedStatus); + ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(resolvedStatus, resolvedMessage); problemDetail.setProperty("traceId", traceId); problemDetail.setProperty("timestamp", Instant.now()); return problemDetail; } } + log.error("[TraceID: {}] Error in {} | Message: {} | Status: {}", + traceId, location, ex.getMessage(), resolvedStatus); // Default Fallback ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail( - HttpStatus.INTERNAL_SERVER_ERROR, - "Internal Server Error. Please contact technical support."); + resolvedStatus, resolvedMessage);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/io/github/og4dev/exception/GlobalExceptionHandler.java` around lines 162 - 173, The log currently hardcodes HttpStatus.INTERNAL_SERVER_ERROR before checking the ApiExceptionRegistry, causing incorrect logged status for mapped exceptions; update GlobalExceptionHandler so it looks up registry.getRule(ex.getClass()) first (if registry != null) to obtain the actual HttpStatus (rule.getStatus()) and use that status value in the log.error call (and when constructing ProblemDetail via ProblemDetail.forStatusAndDetail), falling back to HttpStatus.INTERNAL_SERVER_ERROR only when no rule exists; refer to ApiExceptionRegistry.ExceptionRule, registry.getRule(...), ProblemDetail.forStatusAndDetail and the existing log.error invocation to find and replace the status usage.
98-111:⚠️ Potential issue | 🟠 Major | ⚡ Quick winConstructor injection regression: registry will be null with dual constructors, disabling custom exception mappings.
With both a no-arg and parameterized constructor present, Spring's constructor-resolution algorithm does not reliably select the parameterized constructor when the
@Autowiredannotation is only on the parameter. Spring will fall back to the no-arg constructor when it cannot satisfy the parameterized candidate, leavingregistrynull and effectively disabling all custom exception mapping rules at runtime.Add
@Autowired(required = false)to the parameterized constructor itself (not the parameter) to ensure deterministic constructor selection:Suggested fix
public GlobalExceptionHandler() {} - public GlobalExceptionHandler(`@Autowired`(required = false) ApiExceptionRegistry registry) { + `@Autowired`(required = false) + public GlobalExceptionHandler(ApiExceptionRegistry registry) { this.registry = registry; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/io/github/og4dev/exception/GlobalExceptionHandler.java` around lines 98 - 111, The parameterized constructor in GlobalExceptionHandler is not reliably chosen by Spring because `@Autowired` is placed on the parameter while a no-arg constructor also exists; move the injection annotation to the constructor itself by annotating the constructor with `@Autowired`(required = false) (and remove the `@Autowired` from the parameter) so Spring deterministically injects ApiExceptionRegistry into the GlobalExceptionHandler.registry field when present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/test/java/io/github/og4dev/config/AdvancedStringDeserializerTest.java`:
- Around line 297-303: The test method
classTrimFieldXss_allowsHtmlOnPlainField_sinceNoXssCheck currently feeds plain
text instead of HTML; update the JSON payload string in that test so the "plain"
property contains HTML (e.g. "<b>safe</b>") and adjust the assertion on
ClassTrimFieldXssDto.result.plain to expect the exact HTML value (ensuring
objectMapper.readValue still deserializes to ClassTrimFieldXssDto and that the
"plain" field preserves the HTML).
---
Outside diff comments:
In `@src/main/java/io/github/og4dev/exception/GlobalExceptionHandler.java`:
- Around line 162-173: The log currently hardcodes
HttpStatus.INTERNAL_SERVER_ERROR before checking the ApiExceptionRegistry,
causing incorrect logged status for mapped exceptions; update
GlobalExceptionHandler so it looks up registry.getRule(ex.getClass()) first (if
registry != null) to obtain the actual HttpStatus (rule.getStatus()) and use
that status value in the log.error call (and when constructing ProblemDetail via
ProblemDetail.forStatusAndDetail), falling back to
HttpStatus.INTERNAL_SERVER_ERROR only when no rule exists; refer to
ApiExceptionRegistry.ExceptionRule, registry.getRule(...),
ProblemDetail.forStatusAndDetail and the existing log.error invocation to find
and replace the status usage.
- Around line 98-111: The parameterized constructor in GlobalExceptionHandler is
not reliably chosen by Spring because `@Autowired` is placed on the parameter
while a no-arg constructor also exists; move the injection annotation to the
constructor itself by annotating the constructor with `@Autowired`(required =
false) (and remove the `@Autowired` from the parameter) so Spring
deterministically injects ApiExceptionRegistry into the
GlobalExceptionHandler.registry field when present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9fe33833-40d5-4ddb-84b9-52a0abcd02dd
📒 Files selected for processing (7)
pom.xmlsrc/main/java/io/github/og4dev/exception/GlobalExceptionHandler.javasrc/test/java/io/github/og4dev/advice/GlobalResponseWrapperTest.javasrc/test/java/io/github/og4dev/annotation/AutoResponseAnnotationTest.javasrc/test/java/io/github/og4dev/config/AdvancedStringDeserializerTest.javasrc/test/java/io/github/og4dev/exception/ApiExceptionRegistryTest.javasrc/test/java/io/github/og4dev/exception/GlobalExceptionHandlerTest.java
…lerTest to use parameterized tests for better coverage
Summary by CodeRabbit
Bug Fixes
Tests