Skip to content

Add a lazy composition root to application services#10

Open
koder95 wants to merge 3 commits into
mainfrom
codex/propose-lazy-initialization-and-di-system
Open

Add a lazy composition root to application services#10
koder95 wants to merge 3 commits into
mainfrom
codex/propose-lazy-initialization-and-di-system

Conversation

@koder95
Copy link
Copy Markdown
Contributor

@koder95 koder95 commented May 7, 2026

Motivation

  • Wprowadzić leniwą inicjalizację i prosty composition root aby odroczyć koszt tworzenia zależności do momentu faktycznego użycia usług.
  • Utrzymać DI przez konstruktor w implementacjach serwisów, dzięki czemu zależności pozostają jawne i testowalne.
  • Zakomunikować aktualny stan architektury i kroki potrzebne, aby zbliżyć projekt do zasad Clean Architecture (w szczególności wyodrębnienie adapterów infrastrukturalnych spoza domeny).

Description

  • Dodano nowy pakiet pl.vtt.wpi.core.application.context z interfejsem ApplicationServices będącym fasadą dla przypadków użycia biblioteki. (src/main/java/pl/vtt/wpi/core/application/context/ApplicationServices.java).
  • Dodano thread-safe memoizujący Lazy<T> i implementację LazyApplicationServices z builderem, które rejestrują dostawców portów i tworzą konkretne serwisy dopiero przy pierwszym wywołaniu; zależności przekazywane są przez konstruktory istniejących implementacji usług. (src/main/java/pl/vtt/wpi/core/application/context/Lazy.java, .../LazyApplicationServices.java).
  • Zaktualizowano module-info.java, aby eksportować pakiet application.context i udostępnić composition root klientom modułu. (src/main/java/module-info.java).
  • Dodano testy jednostkowe pokrywające zachowanie leniwej inicjalizacji, nierozwiązywanie niepowiązanych zależności oraz sprawdzanie wymagalności supplierów, oraz dokument z analizą architektury i wskazówkami migracji ku Clean Architecture. (src/test/java/pl/vtt/wpi/core/application/context/LazyApplicationServicesTest.java, docs/architecture-proposal.md).

Testing

  • Skompilowano źródła poleceniem javac --release 25 -d /tmp/wpi-core-classes $(find src/main/java -name '*.java') i kompilacja zakończyła się pomyślnie.
  • git diff --check nie zgłosiło problemów statycznych w zmianach (brak konfliktów/whitespace errors).
  • Próba uruchomienia testów z mvn test zakończyła się niepowodzeniem z powodu niemożności pobrania maven-resources-plugin:3.3.1 (HTTP 403), a mvn -o test również nie mogło uruchomić testów ponieważ wymagany plugin nie był dostępny w lokalnym cache.

Codex Task

Summary by CodeRabbit

  • New Features

    • Lazy, constructor-based composition root for on-demand creation of application services to reduce startup cost.
  • Chores

    • Reorganized boundary between domain and HTTP/infrastructure: moved endpoint and DTO concerns into infrastructure and adjusted module exports.
    • Aligned service APIs to reference infrastructure DTOs where appropriate.
  • Documentation

    • Updated architecture proposal and README to clarify ports/adapters and composition approach.
  • Tests

    • Added tests for lazy initialization and updated adapter/DTO/port tests.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a3583a02-0de2-44d7-8098-8a4e1c10045b

📥 Commits

Reviewing files that changed from the base of the PR and between 2025b10 and 8e5e98e.

📒 Files selected for processing (2)
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataOutputPort.java
  • src/test/java/pl/vtt/wpi/core/domain/port/RuntimeDataOutputPortTest.java

📝 Walkthrough

Walkthrough

This pull request introduces a dependency injection composition root using lazy initialization and constructor-based wiring. It establishes Clean Architecture alignment by separating domain ports from HTTP-specific infrastructure, exports a new application.context package, and implements lazy service instantiation via a builder-configured facade.

Changes

Clean Architecture Composition Root

Layer / File(s) Summary
Architecture Design & Rationale
docs/architecture-proposal.md, README.md
Documents current HTTP-specific logic in domain ports as a Clean Architecture violation, proposes lazy initialization with constructor-based DI in application.context, and lists concrete alignment steps: moving endpoint communication to adapters, keeping domain ports HTTP-agnostic, splitting use-case from gateway ports, and relocating transport DTOs.
Service Facade Contract
src/main/java/pl/vtt/wpi/core/application/context/ApplicationServices.java
Defines public ApplicationServices interface exposing accessors for nine use-case services: LoginService, AdminPasswordService, UserManagementService, RuntimeDataService, PixelProgramService, NetworkConfigurationService, DeviceInfoService, DebugService, RebootService.
Lazy Memoization Utility
src/main/java/pl/vtt/wpi/core/application/context/Lazy.java
Implements thread-safe Lazy<T> supplier that defers initialization until first get() call using double-checked locking with volatile fields, caches the result, and enforces non-null initializer and value constraints.
Composition Root Implementation
src/main/java/pl/vtt/wpi/core/application/context/LazyApplicationServices.java
Implements ApplicationServices with lazy port suppliers and service instances; wires ports into *Impl constructors on first access; includes fluent Builder for configuring port suppliers and producing configured ApplicationServices instances.
Public API Export
src/main/java/module-info.java
Exports pl.vtt.wpi.core.application.context package and infrastructure adapter/dto packages; removes domain dto/port exports.
Application service imports
src/main/java/pl/vtt/wpi/core/application/service/...
Service interfaces/impls updated to reference infrastructure DTOs (PasswordDto, UserCreateRequest, AdminPasswordResetRequest) rather than domain.dto package.
Infrastructure Adapter Moves
src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/...
Relocates concrete InputPort/OutputPort classes from domain.port.* into pl.vtt.wpi.core.infrastructure.adapter.http without behavior changes; tests updated to import new FQNs.
Infrastructure DTO Moves
src/main/java/pl/vtt/wpi/core/infrastructure/dto/...
Moves transport DTO records (PasswordDto, UserCreateRequest, AdminPasswordResetRequest) from pl.vtt.wpi.core.domain.dto into pl.vtt.wpi.core.infrastructure.dto; records unchanged.
RuntimeData OutputPort interrupt handling
src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataOutputPort.java
Catch block updated to restore thread interrupted status when catching InterruptedException before throwing OutputPortException.
Tests
src/test/java/...
Adds LazyApplicationServicesTest verifying lazy initialization, caching, selective resolution, and fail-fast builder; updates many unit tests to import infrastructure adapter implementations and infrastructure DTOs; adds interrupt-preservation test for RuntimeDataOutputPort.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 "I hopped through packages, light and spry,

Moved DTOs and ports where protocols fly.
Builders ready, Lazy waits to spin,
Services wake only when calls begin.
A tidy root — now clean, let's hop and grin."

🚥 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 a lazy composition root to application services' directly and clearly describes the main architectural change introduced in this PR: the addition of lazy initialization and a composition root pattern to the application services layer.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/propose-lazy-initialization-and-di-system

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.

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

🤖 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/main/java/pl/vtt/wpi/core/application/context/Lazy.java`:
- Around line 30-38: The branch in Lazy.get() that handles currentInitializer ==
null can never legitimately run and currently assigns a null to current,
violating the non-null contract; replace this dead guard with an explicit
failure (e.g., throw an AssertionError or IllegalStateException) to make the
invariant explicit and fail fast. Locate the synchronized block in class Lazy
(the method using variables initializer, value, current and Supplier<? extends
T>) and swap the "if (currentInitializer == null) { current = value; }" branch
for an assertion/exception indicating invariant violation (include a clear
message referencing initializer/value) so any unexpected state is loudly
reported instead of returning null.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 750444fd-1003-43d7-8e35-2115084f3896

📥 Commits

Reviewing files that changed from the base of the PR and between 386e4a5 and 8c0ae3e.

📒 Files selected for processing (6)
  • docs/architecture-proposal.md
  • src/main/java/module-info.java
  • src/main/java/pl/vtt/wpi/core/application/context/ApplicationServices.java
  • src/main/java/pl/vtt/wpi/core/application/context/Lazy.java
  • src/main/java/pl/vtt/wpi/core/application/context/LazyApplicationServices.java
  • src/test/java/pl/vtt/wpi/core/application/context/LazyApplicationServicesTest.java

Comment thread src/main/java/pl/vtt/wpi/core/application/context/Lazy.java Outdated
@koder95 koder95 changed the title Dodaj leniwy composition root dla serwisów aplikacyjnych Add a lazy composition root to application services May 8, 2026
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.

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/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataOutputPort.java (1)

25-27: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Restore interrupt status on InterruptedException — inconsistent with peer OutputPort adapters.

Both DeviceInfoOutputPort and UsersOutputPort in this same package check for InterruptedException and call Thread.currentThread().interrupt() before re-throwing. RuntimeDataOutputPort silently clears the interrupt flag.

🐛 Proposed fix
     } catch (Exception e) {
+        if (e instanceof InterruptedException) {
+            Thread.currentThread().interrupt();
+        }
         throw new OutputPortException("Cannot load runtime data", e);
     }
🤖 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/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataOutputPort.java`
around lines 25 - 27, In RuntimeDataOutputPort's exception handling (the
catch(Exception e) that throws new OutputPortException("Cannot load runtime
data", e)), detect if the caught exception is an InterruptedException and if so
call Thread.currentThread().interrupt() before rethrowing the
OutputPortException; mirror the behavior in DeviceInfoOutputPort and
UsersOutputPort so the thread's interrupt status is preserved when wrapping the
exception into OutputPortException.
🤖 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.

Outside diff comments:
In
`@src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataOutputPort.java`:
- Around line 25-27: In RuntimeDataOutputPort's exception handling (the
catch(Exception e) that throws new OutputPortException("Cannot load runtime
data", e)), detect if the caught exception is an InterruptedException and if so
call Thread.currentThread().interrupt() before rethrowing the
OutputPortException; mirror the behavior in DeviceInfoOutputPort and
UsersOutputPort so the thread's interrupt status is preserved when wrapping the
exception into OutputPortException.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 879dcedb-0268-433d-893f-06e7fa031413

📥 Commits

Reviewing files that changed from the base of the PR and between 8c0ae3e and 2025b10.

📒 Files selected for processing (40)
  • README.md
  • docs/architecture-proposal.md
  • src/main/java/module-info.java
  • src/main/java/pl/vtt/wpi/core/application/context/ApplicationServices.java
  • src/main/java/pl/vtt/wpi/core/application/context/Lazy.java
  • src/main/java/pl/vtt/wpi/core/application/context/LazyApplicationServices.java
  • src/main/java/pl/vtt/wpi/core/application/service/AdminPasswordService.java
  • src/main/java/pl/vtt/wpi/core/application/service/UserManagementService.java
  • src/main/java/pl/vtt/wpi/core/application/service/impl/AdminPasswordServiceImpl.java
  • src/main/java/pl/vtt/wpi/core/application/service/impl/UserManagementServiceImpl.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/AuthOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/CurrentStateOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/DeviceInfoOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/LogsDeleteInputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/PixelProgramsInputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/PixelProgramsOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/RestartInputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataInputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/RuntimeDataOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/UserCreateInputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/UsersOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/WifiConfigInputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/dto/AdminPasswordResetRequest.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/dto/PasswordDto.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/dto/UserCreateRequest.java
  • src/test/java/pl/vtt/wpi/core/application/context/LazyApplicationServicesTest.java
  • src/test/java/pl/vtt/wpi/core/application/service/impl/AdminPasswordServiceImplTest.java
  • src/test/java/pl/vtt/wpi/core/application/service/impl/UserManagementServiceImplTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/AuthOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/CurrentStateOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/DeviceInfoOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/LogsDeleteInputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/PixelProgramsInputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/PixelProgramsOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/RestartInputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/RuntimeDataInputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/RuntimeDataOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/UserCreateInputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/UsersOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/WifiConfigInputPortTest.java
✅ Files skipped from review due to trivial changes (14)
  • src/main/java/pl/vtt/wpi/core/application/service/AdminPasswordService.java
  • src/test/java/pl/vtt/wpi/core/application/service/impl/AdminPasswordServiceImplTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/DeviceInfoOutputPortTest.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/dto/UserCreateRequest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/UsersOutputPortTest.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/AuthOutputPort.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/CurrentStateOutputPort.java
  • src/main/java/pl/vtt/wpi/core/application/service/impl/AdminPasswordServiceImpl.java
  • src/test/java/pl/vtt/wpi/core/domain/port/RestartInputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/RuntimeDataOutputPortTest.java
  • src/main/java/pl/vtt/wpi/core/infrastructure/adapter/http/PixelProgramsOutputPort.java
  • src/test/java/pl/vtt/wpi/core/domain/port/AuthOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/domain/port/CurrentStateOutputPortTest.java
  • src/test/java/pl/vtt/wpi/core/application/context/LazyApplicationServicesTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/pl/vtt/wpi/core/application/context/ApplicationServices.java
  • src/main/java/pl/vtt/wpi/core/application/context/LazyApplicationServices.java
  • src/main/java/pl/vtt/wpi/core/application/context/Lazy.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant