Skip to content

Add typed exception hierarchy#21

Merged
rammrain merged 2 commits into
mainfrom
feature/typed-exception-hierarchy
Apr 10, 2026
Merged

Add typed exception hierarchy#21
rammrain merged 2 commits into
mainfrom
feature/typed-exception-hierarchy

Conversation

@rammrain
Copy link
Copy Markdown
Member

@rammrain rammrain commented Apr 10, 2026

Summary

  • Introduces MontonioException base class and four specific subtypes: MontonioApiException, MontonioNetworkException, MontonioAuthenticationException, and MontonioValidationException
  • Each exception carries typed context fields (e.g., HTTP status code, error code, field name) for consumer-friendly error handling
  • Includes design document in docs/plans/

Design decisions

Decision Choice
Hierarchy Flat — 4 final siblings under MontonioException
Checked/unchecked All unchecked (RuntimeException)
Validation Fail-fast (single error per exception)
Boilerplate Lombok @Getter; hand-written constructors for super() delegation

Test plan

  • Unit tests for all 5 exception classes
  • Message formatting tested for all nullable field combinations
  • Cause chaining verified
  • ./gradlew test passes

Closes #13

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Introduced a typed exception hierarchy with distinct exceptions for API responses, authentication failures, network issues and validation errors, each producing consistent, formatted messages and exposing relevant details.
  • Documentation

    • Added a design proposal describing the typed exception hierarchy and planned behaviours.
  • Tests

    • Added comprehensive unit tests covering construction, message formatting (including null cases), cause propagation and type relationships for all exception types.

Introduces MontonioException base and four specific subtypes:
MontonioApiException, MontonioNetworkException,
MontonioAuthenticationException, and MontonioValidationException.
Each carries typed context fields for consumer-friendly error handling.

Closes #13

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f61bc470-7c30-49ad-94dd-18ad017257ad

📥 Commits

Reviewing files that changed from the base of the PR and between 80d5a4c and 34001e3.

📒 Files selected for processing (3)
  • docs/plans/2026-04-10-typed-exception-hierarchy-design.md
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioValidationException.java
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioValidationExceptionTest.java
✅ Files skipped from review due to trivial changes (2)
  • docs/plans/2026-04-10-typed-exception-hierarchy-design.md
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioValidationException.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioValidationExceptionTest.java

📝 Walkthrough

Walkthrough

Introduces a flat unchecked exception hierarchy for the Montonio SDK: MontonioException (base) plus four final subclasses (MontonioApiException, MontonioNetworkException, MontonioAuthenticationException, MontonioValidationException), along with a design doc and unit tests covering construction, message formatting and cause propagation.

Changes

Cohort / File(s) Summary
Design Documentation
docs/plans/2026-04-10-typed-exception-hierarchy-design.md
New design doc specifying the exception hierarchy, constructor signatures, message formatting rules, nullable-field handling, and a per-exception unit-test plan.
Base Exception
src/main/java/ee/bitweb/montonio/sdk/exception/MontonioException.java
Added base runtime exception with two constructors: message-only and message+cause.
API Exception
src/main/java/ee/bitweb/montonio/sdk/exception/MontonioApiException.java
New final class carrying statusCode, nullable errorCode and errorMessage; constructs a formatted message that conditionally includes bracketed code and/or message.
Network & Auth Exceptions
src/main/java/ee/bitweb/montonio/sdk/exception/MontonioNetworkException.java, src/main/java/ee/bitweb/montonio/sdk/exception/MontonioAuthenticationException.java
Added MontonioNetworkException (message + cause) and MontonioAuthenticationException (message or message+cause) as final subclasses delegating to base constructors.
Validation Exception
src/main/java/ee/bitweb/montonio/sdk/exception/MontonioValidationException.java
New final class with optional field getter; multiple constructors format messages as either Validation failed on field '<field>': <message> or Validation failed: <message> and support optional cause.
Unit Tests
src/test/java/ee/bitweb/montonio/sdk/exception/...
Added JUnit 5 tests for each exception type validating constructor behaviour, message formatting (including null cases), cause chaining, getters, and type relationships (instanceof checks).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I’m a rabbit with a tidy stack trace,
New exceptions hop into place,
API, Network, Auth and Validation too,
Messages neat, causes kept true,
Hooray — fewer surprises in the race! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add typed exception hierarchy' is concise, clear and directly summarises the main change—introduction of a structured exception hierarchy with a base class and four concrete exception types.
Linked Issues check ✅ Passed All requirements from issue #13 are fully met: base MontonioException extending RuntimeException, four concrete exception types (MontonioApiException, MontonioNetworkException, MontonioAuthenticationException, MontonioValidationException) each carrying contextual fields, comprehensive unit tests covering construction, message formatting, cause chaining and accessors.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the typed exception hierarchy objective; no unrelated modifications detected. Changes include the five exception classes, design documentation, and complete unit test coverage per specification.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/typed-exception-hierarchy

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

Copy link
Copy Markdown

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

🧹 Nitpick comments (1)
src/main/java/ee/bitweb/montonio/sdk/exception/MontonioApiException.java (1)

19-35: Consider treating blank strings as absent in message formatting.

null is handled well, but empty/blank errorCode or errorMessage may still render awkward output ([] or trailing : ). Normalising blanks would make messages cleaner in edge cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/ee/bitweb/montonio/sdk/exception/MontonioApiException.java`
around lines 19 - 35, The message formatter formatMessage in
MontonioApiException should treat empty or whitespace-only errorCode and
errorMessage as absent: normalize both inputs (trim and check isEmpty or use
StringUtils.isBlank) before building the StringBuilder, replace null checks with
blank-aware checks so you avoid producing "[]", trailing ": " or stray
spaces/punctuation, and ensure the conditional branches around appending the
colon, brackets and space use these normalized booleans (e.g., hasErrorCode,
hasErrorMessage) to decide what to append.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/plans/2026-04-10-typed-exception-hierarchy-design.md`:
- Line 21: Replace the phrase "hand-written" with "handwritten" in the table
cell that currently reads "Lombok `@Getter`; hand-written constructors" so the
text reads "Lombok `@Getter`; handwritten constructors"; update that exact
string wherever it appears (e.g., the table row under the "Boilerplate" column)
to fix the wording/spelling.
- Around line 25-31: The fenced code block showing the exception hierarchy lacks
a language hint; update the block by adding a language tag (e.g., "text") after
the opening triple backticks so the snippet renders correctly and satisfies
markdown linting — apply this change to the block containing MontonioException
and its subclasses (MontonioApiException, MontonioNetworkException,
MontonioAuthenticationException, MontonioValidationException).

In
`@src/main/java/ee/bitweb/montonio/sdk/exception/MontonioValidationException.java`:
- Around line 20-22: The formatMessage method in MontonioValidationException
currently inserts null or blank field names literally; update
formatMessage(String field, String message) to sanitize the field parameter
(e.g., treat null or blank as a default like "<unknown>" or omit the field
label) before building the string so the resulting message is not "null" or
empty; ensure the field-based constructor that calls formatMessage uses this
sanitized output so validation messages remain clear and consistent.
- Around line 10-18: MontonioValidationException currently has two constructors
that don't accept a cause, losing upstream Throwable context; add two additional
cause-aware constructors—one matching public MontonioValidationException(String
field, String message) but with a Throwable cause and one matching public
MontonioValidationException(String message) with a Throwable cause—each should
call super(formattedMessage, cause) (use formatMessage(field, message) for the
field variant) and set this.field appropriately so callers can wrap
parse/normalisation failures without losing the root cause.

---

Nitpick comments:
In `@src/main/java/ee/bitweb/montonio/sdk/exception/MontonioApiException.java`:
- Around line 19-35: The message formatter formatMessage in MontonioApiException
should treat empty or whitespace-only errorCode and errorMessage as absent:
normalize both inputs (trim and check isEmpty or use StringUtils.isBlank) before
building the StringBuilder, replace null checks with blank-aware checks so you
avoid producing "[]", trailing ": " or stray spaces/punctuation, and ensure the
conditional branches around appending the colon, brackets and space use these
normalized booleans (e.g., hasErrorCode, hasErrorMessage) to decide what to
append.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6d122b8-288e-4fbc-9896-2537490c49ec

📥 Commits

Reviewing files that changed from the base of the PR and between b95bb7d and 80d5a4c.

📒 Files selected for processing (11)
  • docs/plans/2026-04-10-typed-exception-hierarchy-design.md
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioApiException.java
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioAuthenticationException.java
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioException.java
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioNetworkException.java
  • src/main/java/ee/bitweb/montonio/sdk/exception/MontonioValidationException.java
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioApiExceptionTest.java
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioAuthenticationExceptionTest.java
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioExceptionTest.java
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioNetworkExceptionTest.java
  • src/test/java/ee/bitweb/montonio/sdk/exception/MontonioValidationExceptionTest.java

Comment thread docs/plans/2026-04-10-typed-exception-hierarchy-design.md Outdated
Comment thread docs/plans/2026-04-10-typed-exception-hierarchy-design.md Outdated
- Fix "hand-written" -> "handwritten" in design doc
- Add language hint to fenced code block in design doc
- Add cause-aware constructors to MontonioValidationException

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rammrain rammrain merged commit c1befdf into main Apr 10, 2026
5 checks passed
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.

Typed exception hierarchy

1 participant