Skip to content

feature : Architecture testing - #43

Merged
FionaSprinkles merged 5 commits into
mainfrom
feature/arch-test
Apr 24, 2026
Merged

feature : Architecture testing#43
FionaSprinkles merged 5 commits into
mainfrom
feature/arch-test

Conversation

@FionaSprinkles

@FionaSprinkles FionaSprinkles commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Introduces ArchUnit tests to enforce a clean layered architecture in the project.

Summary by CodeRabbit

  • Documentation

    • Added an Architecture section to the README describing the layered structure and responsibilities.
  • Tests

    • Added architecture validation tests enforcing separation of concerns and package placement rules.
  • Refactor

    • Controllers now obtain attachments and audit logs via service-layer calls instead of direct repository access; service layer exposes methods to fetch attachments and audit logs.

@coderabbitai

coderabbitai Bot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@addee1 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 39 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 49 minutes and 39 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bab0a21a-4f91-4231-8cd9-2fbb18c9d5fb

📥 Commits

Reviewing files that changed from the base of the PR and between a76b45b and ce37c00.

📒 Files selected for processing (5)
  • src/main/java/org/example/alfs/controllers/AttachmentController.java
  • src/main/java/org/example/alfs/controllers/AttachmentDownloadController.java
  • src/main/java/org/example/alfs/controllers/AuthController.java
  • src/main/java/org/example/alfs/controllers/TicketCommentController.java
  • src/main/java/org/example/alfs/services/AttachmentService.java
📝 Walkthrough

Walkthrough

Moves direct repository access out of controllers into services, adds service methods for attachment/audit retrieval, updates controller constructors and usages accordingly, adds ArchUnit test suite and dependency, and documents the architecture in README. No production-facing API signatures were removed.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added "Architecture" section describing layered structure and responsibilities (Controller → Service → Repository → Database).
Build Configuration
pom.xml
Added com.tngtech.archunit:archunit:1.4.2 as a test-scoped dependency.
Architecture Tests
src/test/java/org/example/alfs/ArchitectureTest.java
New ArchUnit test suite with rules enforcing layer separation, package placement for Controller/Service/Repository classes, and DTO↛Entity dependency prohibition.
Controllers (dependency changes)
src/main/java/org/example/alfs/controllers/AttachmentController.java, .../AttachmentDownloadController.java, .../TicketController.java
Removed direct *Repository injections; constructors now inject AttachmentService and AuditService where applicable. Controller methods delegate attachment/audit retrieval to service methods instead of repository calls; download endpoint delegates attachment lookup to service.
Services (new APIs)
src/main/java/org/example/alfs/services/AttachmentService.java, .../AuditService.java
Added AttachmentService.getAttachmentsByTicketId(Long) and getAttachmentById(Long); added AuditService.getAuditLogsForTicket(Long). New methods use existing repositories and translate missing attachments into 404 ResponseStatusException.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Controller
  participant Service
  participant Repository
  participant Minio as MinioStorageService

  Client->>Controller: request /tickets/{id} or /token/{token}
  Controller->>Service: getAttachmentsByTicketId(ticketId)
  Service->>Repository: findByTicketId(ticketId)
  Repository-->>Service: List<Attachment>
  Service-->>Controller: List<Attachment>
  Controller->>Service: getAuditLogsForTicket(ticketId)
  Service->>Repository: findByTicketIdOrderByCreatedAtDesc(ticketId)
  Repository-->>Service: List<AuditLog>
  Service-->>Controller: List<AuditLog>
  alt Download attachment endpoint
    Client->>Controller: GET /attachments/{id}/download
    Controller->>Service: getAttachmentById(id)
    Service->>Repository: findById(id)
    Repository-->>Service: Attachment
    Service-->>Controller: Attachment
    Controller->>Minio: downloadObject(attachment.path)
    Minio-->>Controller: InputStream / error
    Controller-->>Client: streaming response / error
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • simonforsberg

Poem

🐰 Hopping through code with a twitch and a grin,
I moved repositories out — let services begin.
Tests watch the layers, README hums the tune,
Attachments and audits now pass by the moon. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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 accurately reflects the main purpose: introducing ArchUnit-based architecture testing to enforce clean layered architecture patterns.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/arch-test

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
src/test/java/org/example/alfs/ArchitectureTest.java (1)

84-89: Narrow the documented JwtService exception.

The comment says only JwtService is exempt, but Line 88 allows any *Service class under ..security... Split this into the default *Service → ..services.. rule plus a targeted JwtService → ..security.. exception so future services cannot bypass the package rule accidentally.

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

In `@src/test/java/org/example/alfs/ArchitectureTest.java` around lines 84 - 89,
Update the test so the broad „*Service -> ..security..“ allowance is removed and
replaced by two targeted rules: keep the default rule in
services_should_be_in_services_package that asserts
classes().that().haveSimpleNameEndingWith("Service").should().resideInAnyPackage("..services..")
and add a second, separate rule that explicitly asserts
classes().that().haveSimpleName("JwtService").should().resideInAnyPackage("..security..");
call check(classes) on both rules so JwtService is the only service allowed in
the security package and other *Service classes cannot bypass the packages rule.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/test/java/org/example/alfs/ArchitectureTest.java`:
- Around line 31-62: Remove the unused repository imports from the three
controller classes (TicketController, AttachmentController,
AttachmentDownloadController) so ArchUnit tests
controllers_should_only_access_services_not_repositories and
controllers_dto_and_mapper_should_not_access_repositories no longer fail due to
mere imports; locate any import statements referencing repository types in those
controllers and either (a) move repository usage behind the appropriate service
and inject the service instead, or (b) delete the unused import and any dead
code that referenced it, and then re-run the tests to ensure controllers only
depend on services (methods:
controllers_should_only_access_services_not_repositories,
controllers_dto_and_mapper_should_not_access_repositories).

---

Nitpick comments:
In `@src/test/java/org/example/alfs/ArchitectureTest.java`:
- Around line 84-89: Update the test so the broad „*Service -> ..security..“
allowance is removed and replaced by two targeted rules: keep the default rule
in services_should_be_in_services_package that asserts
classes().that().haveSimpleNameEndingWith("Service").should().resideInAnyPackage("..services..")
and add a second, separate rule that explicitly asserts
classes().that().haveSimpleName("JwtService").should().resideInAnyPackage("..security..");
call check(classes) on both rules so JwtService is the only service allowed in
the security package and other *Service classes cannot bypass the packages rule.
🪄 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: 231a4256-74f7-4c22-81f7-797cd83d8288

📥 Commits

Reviewing files that changed from the base of the PR and between 41c00e6 and 6ce01d1.

📒 Files selected for processing (3)
  • README.md
  • pom.xml
  • src/test/java/org/example/alfs/ArchitectureTest.java

Comment on lines +31 to +62
@Test
void controllers_should_only_access_services_not_repositories() {
noClasses()
.that().resideInAPackage("..controllers..")
.should().dependOnClassesThat()
.resideInAPackage("..repositories..")
.check(classes);
}

@Test
void services_should_not_depend_on_controllers() {
noClasses()
.that().resideInAPackage("..services..")
.should().dependOnClassesThat()
.resideInAPackage("..controllers..")
.check(classes);
}

/**
* Repository Access Rule
*
* Controllers, DTOs and mappers must not access repositories directly.
* Repository access should go through the service layer.
*/
@Test
void controllers_dto_and_mapper_should_not_access_repositories() {
noClasses()
.that().resideInAnyPackage("..controllers..", "..dto..", "..mapper..")
.should().dependOnClassesThat()
.resideInAPackage("..repositories..")
.check(classes);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify controller classes that directly import repositories and will fail the new architecture rules.
fd -e java 'Controller\.java$' \
  | xargs rg -nP -C2 '^\s*import\s+org\.example\.alfs\.repositories\.'

Repository: ithsjava25/project-backend-alfs

Length of output: 1911


🏁 Script executed:

cat -n src/test/java/org/example/alfs/ArchitectureTest.java

Repository: ithsjava25/project-backend-alfs

Length of output: 4390


🏁 Script executed:

# Check if repositories are actually called/used in each controller, not just imported
for controller in TicketController AttachmentController AttachmentDownloadController; do
  echo "=== $controller ==="
  rg -n "new\s+\w*Repository|repository\." "src/main/java/org/example/alfs/controllers/${controller}.java" || echo "No repository usage found"
done

Repository: ithsjava25/project-backend-alfs

Length of output: 243


🏁 Script executed:

# Check the exact lines mentioned in the review for the supposed duplicate rule
sed -n '31,62p' src/test/java/org/example/alfs/ArchitectureTest.java | cat -n

Repository: ithsjava25/project-backend-alfs

Length of output: 1403


Remove unused repository imports before enabling these architecture rules.

The three controllers (TicketController, AttachmentController, AttachmentDownloadController) import repository classes that are not actually used in the code. ArchUnit will fail the architecture tests on these imports alone. Either move the logic behind services or remove the unused imports before merging.

The controllers_dto_and_mapper_should_not_access_repositories() rule (lines 56–61) is not a duplicate of the earlier controller rule—it additionally covers DTOs and mappers, so both tests serve distinct purposes.

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

In `@src/test/java/org/example/alfs/ArchitectureTest.java` around lines 31 - 62,
Remove the unused repository imports from the three controller classes
(TicketController, AttachmentController, AttachmentDownloadController) so
ArchUnit tests controllers_should_only_access_services_not_repositories and
controllers_dto_and_mapper_should_not_access_repositories no longer fail due to
mere imports; locate any import statements referencing repository types in those
controllers and either (a) move repository usage behind the appropriate service
and inject the service instead, or (b) delete the unused import and any dead
code that referenced it, and then re-run the tests to ensure controllers only
depend on services (methods:
controllers_should_only_access_services_not_repositories,
controllers_dto_and_mapper_should_not_access_repositories).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 (1)
src/main/java/org/example/alfs/controllers/AttachmentController.java (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Remove the stale AttachmentRepository import.

AttachmentRepository is no longer referenced in this controller after the refactor, and leaving the import contradicts the architectural intent of this PR (controllers must not depend on repository packages — the exact rule the new ArchUnit suite enforces). Whether ArchUnit catches it depends on whether its rule runs on importedClasses or only resolved references, so drop it explicitly.

🔧 Proposed fix
 import org.example.alfs.services.AttachmentService;
-import org.example.alfs.repositories.AttachmentRepository;
 import org.springframework.http.HttpStatus;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/org/example/alfs/controllers/AttachmentController.java` at line
7, The AttachmentController currently contains a stale import of
org.example.alfs.repositories.AttachmentRepository which is no longer referenced
and violates the new ArchUnit rule (controllers must not depend on repository
packages); remove the unused import statement for AttachmentRepository from
AttachmentController (class name: AttachmentController) so the controller only
imports needed service/DTO classes and no repository package references, then
run/build to ensure no remaining compilation errors or unused-import warnings.
🧹 Nitpick comments (1)
src/main/java/org/example/alfs/controllers/TicketController.java (1)

31-38: LGTM.

Constructor now correctly injects AttachmentService/AuditService in place of the prior repositories, and the two view endpoints (/token/{token} and /{id}) consistently delegate attachment and audit reads through the service layer. Aligns with the ArchUnit rules added in this PR.

Minor nit (optional): the constructor signature has a couple of inconsistent spaces (missing space after , before AttachmentService, double space before SecurityUtils). Purely cosmetic.

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

In `@src/main/java/org/example/alfs/controllers/TicketController.java` around
lines 31 - 38, The constructor signature in TicketController has inconsistent
spacing around commas (e.g., no space before AttachmentService and double space
before SecurityUtils); update the TicketController(TicketService ticketService,
TicketCommentService ticketCommentService, AttachmentService attachmentService,
AuditService auditService, SecurityUtils securityUtils, UserService userService)
constructor declaration to use a single space after each comma so the parameter
list is consistently formatted.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/org/example/alfs/controllers/AttachmentDownloadController.java`:
- Around line 5-6: Remove the unused import of AttachmentRepository from
AttachmentDownloadController to avoid a direct controller→repository dependency;
locate the import statement referencing
org.example.alfs.repositories.AttachmentRepository in
AttachmentDownloadController and delete it, ensuring the controller only uses
AttachmentService and calls attachmentService.getAttachmentById(id) (and that
AttachmentService is imported and used) so the ArchitectureTest no longer
detects a repositories dependency.

---

Outside diff comments:
In `@src/main/java/org/example/alfs/controllers/AttachmentController.java`:
- Line 7: The AttachmentController currently contains a stale import of
org.example.alfs.repositories.AttachmentRepository which is no longer referenced
and violates the new ArchUnit rule (controllers must not depend on repository
packages); remove the unused import statement for AttachmentRepository from
AttachmentController (class name: AttachmentController) so the controller only
imports needed service/DTO classes and no repository package references, then
run/build to ensure no remaining compilation errors or unused-import warnings.

---

Nitpick comments:
In `@src/main/java/org/example/alfs/controllers/TicketController.java`:
- Around line 31-38: The constructor signature in TicketController has
inconsistent spacing around commas (e.g., no space before AttachmentService and
double space before SecurityUtils); update the TicketController(TicketService
ticketService, TicketCommentService ticketCommentService, AttachmentService
attachmentService, AuditService auditService, SecurityUtils securityUtils,
UserService userService) constructor declaration to use a single space after
each comma so the parameter list is consistently formatted.
🪄 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: 1b986720-760b-45fc-ad1a-e17961e432d8

📥 Commits

Reviewing files that changed from the base of the PR and between 6ce01d1 and a76b45b.

📒 Files selected for processing (5)
  • src/main/java/org/example/alfs/controllers/AttachmentController.java
  • src/main/java/org/example/alfs/controllers/AttachmentDownloadController.java
  • src/main/java/org/example/alfs/controllers/TicketController.java
  • src/main/java/org/example/alfs/services/AttachmentService.java
  • src/main/java/org/example/alfs/services/AuditService.java

Comment thread src/main/java/org/example/alfs/controllers/AttachmentDownloadController.java Outdated
@addee1

addee1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

@FionaSprinkles @simonforsberg All tests green! Nitpicks fixed. Should be ready to merge if @FionaSprinkles was 100% done with her tests :)

@FionaSprinkles
FionaSprinkles merged commit 76a932f into main Apr 24, 2026
2 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants