Skip to content

refactor: enforce clean layer separation across repository, service, and controller #216

Draft
anderslindho wants to merge 4 commits intomasterfrom
refactor/layer-isolation
Draft

refactor: enforce clean layer separation across repository, service, and controller #216
anderslindho wants to merge 4 commits intomasterfrom
refactor/layer-isolation

Conversation

@anderslindho
Copy link
Copy Markdown
Contributor

Pushes the codebase toward cleaner layering: repositories are pure persistence adapters, services have no web framework dependencies, and the HTTP boundary is explicit.

Also adds a v0 DTO layer ahead of a planned v1 API, so the two can evolve independently without touching the service or domain layers.

Repositories must not know about HTTP. Replace all ResponseStatusException
throws in ChannelRepository, TagRepository, and PropertyRepository with
StorageException (for ES IO failures) or the existing typed domain exceptions
(ChannelValidationException for bad query windows). Add a StorageException
handler to V0ExceptionHandler mapping it to 500.

The NOT_FOUND status used in findById catch blocks was also wrong: those are
IO/connection failures, not 404s - replaced with StorageException.
…itory boundaries

Services must not depend on Spring web binding types. Replace
MultiValueMap<String, String> with Map<String, List<String>> in all
service method signatures and repository public APIs. Controllers pass
their MultiValueMap directly — no conversion needed since MultiValueMap
IS-A Map<String, List<String>>.

Also replaces internal LinkedMultiValueMap usages in TagRepository and
PropertyRepository scroll loops, MetricsService metric-combination
generation, ChannelProcessorService.processAllChannels, and
ChannelFinderEpicsService with standard java.util equivalents.
@repository and @configuration must not be combined on the same class.
The @configuration annotation was causing repositories to participate in
Spring's configuration processing, which is incorrect. Remove it from
all three repositories and drop the now-unused import.
* @return matching channels
*/
public SearchResult search(MultiValueMap<String, String> searchParameters) {
public SearchResult search(Map<String, List<String>> searchParameters) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why replacing MultiValuedMap?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See commit message for that change:

Services must not depend on Spring web binding types. Replace
MultiValueMap<String, String> with Map<String, List> in all
service method signatures and repository public APIs. Controllers pass
their MultiValueMap directly - no conversion needed since MultiValueMap
IS-A Map<String, List>.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

MultiValuedMap is a class in spring framework core, not in a web library.

Copy link
Copy Markdown
Collaborator

@georgweiss georgweiss left a comment

Choose a reason for hiding this comment

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

Added in-line comment

Add ChannelDto, TagDto, PropertyDto, SearchResultDto, ScrollDto under
web/v0/dto/ and corresponding static mappers under web/v0/mapper/.
All five controllers now map to/from DTOs; the service and domain
layers are unchanged.

This isolates the v0 API shape from the domain model so a future v1
API can evolve its own DTOs without touching service or repository code.
@anderslindho anderslindho force-pushed the refactor/layer-isolation branch from ef3dcb7 to 1863ef6 Compare May 7, 2026 13:53
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 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