grant-burgess/clean-architecture-example-java-spring-boot
61.3
Adequate · 21 September 2026
1.1k
lines of production code
Java
primary language
4
measurements over time
What this system is
This system is a Java-based microservice named 'Offer Service' that manages the lifecycle of commercial offers. It provides a REST API for creating, cancelling, and querying offers, with internal logic handling validation, status tracking, and data persistence via JPA. The architecture is modular, separating domain use cases, database adapters, and presentation layers to ensure clear separation of concerns.
Features
Added presenters to map domain models to view models
Introduced new presenter classes (BaseOfferPresenter, OfferCreatedPresenter, OfferPresenter, OffersPresenter) that transform internal use-case response models into view models (OfferViewModel, OfferCreatedViewModel, OffersViewModel) for the UI layer. This change implements the output boundary pattern, ensuring that data is properly formatted and structured for presentation, including date formatting and price scaling.
Presenters · high confidence
Initial JPA database adapter implementation
Added the JPA-based database adapter for managing offers, including the JpaDatabase and JpaOfferGateway classes that map to the OfferData entity and OfferRepository. The implementation supports creating, retrieving, and updating offers while excluding cancelled offers from standard queries. Added corresponding unit tests for the repository layer to verify filtering logic.
DBAdapterJpa · high confidence
Initial commit: introduce Offer entity and Gradle wrapper
The project is initialized with a new Offer entity class in the Entities module, defining a domain model for offers with properties like name, description, start/end dates, and price, along with a nested Money class and status enum. Additionally, the Gradle wrapper configuration is added to manage the build tool version (4.8.1).
Entities, gradle · high confidence
Initial project scaffolding and documentation
The repository was initialized with essential build and configuration files, including a .gitignore for IDE and build artifacts, a .travis.yml for CI/CD, and Gradle wrapper scripts (gradlew, gradlew.bat) to manage the build system. Additionally, a SonarQube configuration file (sonar-project.properties) was added for code quality analysis, and the README.md was expanded to document the 'offer-service' REST API, its architecture, and usage instructions.
(repo-wide) · high confidence
Initial release of the Offer Service application
The application is now available at the /offer-service context path. It exposes REST endpoints for creating, cancelling, and querying offers (by ID and in a list). The API includes Swagger documentation and standardized error handling for validation and gateway exceptions.
Application · high confidence
Introduced AddOffer and CancelOffer use cases
Added new use-case implementations for creating and cancelling offers. The AddOffer use case handles offer creation, including validation of date ranges and name uniqueness, while the CancelOffer use case manages the cancellation of existing offers with appropriate state and date validations.
UseCases/src/main/java/com/grantburgess/usecases/addoffer · high confidence
Behavioural changes
Centralized application wiring in ApplicationModule
The application's Spring configuration has been consolidated into a new \ApplicationConfiguration\ class within the \ApplicationModule\. This change moves the wiring of use cases (AddOffer, CancelOffer, GetOffers, GetOfferById), presenters (OfferCreatedPresenter, OfferPresenter, OffersPresenter), and infrastructure beans (Database, Clock) into a single, pluggable module. This removes the need for extra Spring Boot configuration in the JPA module and centralizes the dependency injection for the application's core logic.
ApplicationModule · high confidence
Defined ports for offer management and presentation
The Ports package now includes interfaces and data models for managing offers, including input boundaries for adding, canceling, and retrieving offers (by ID and in lists), as well as output boundaries and view models for presenting offer details and lists. A database gateway interface and associated exceptions are also introduced to define the data access contract.
Ports · high confidence
Restructured get use cases into a shared base class
The get use cases (GetOfferById and GetOffers) have been refactored to share a common base class (GetOfferBase) that encapsulates the logic for constructing OfferResponse objects and computing their status (active, expired, or cancelled). This change consolidates the response-building logic, ensuring consistent status calculation across both the single-offer and list-offers use cases.
UseCases/src/main/java/com/grantburgess/usecases/get · medium confidence
Test coverage
Added tests for offer use cases and test doubles
Added unit tests for the AddOffer, CancelOffer, GetOfferById, and GetOffers use cases, along with supporting test doubles (ClockStub, OfferCreatedPresenterSpy, OfferPresenterSpy, and OffersPresenterSpy) and an in-memory database implementation (InMemoryDatabase, InMemoryOfferGateway) to verify the behavior of the offer management features.
UseCases/src, UseCases/src/test/java/com/grantburgess/usecases/testdoubles · high confidence
Dependencies
Initial project structure and dependency configuration
The project is initialized with a multi-module Gradle build, defining subprojects for Ports, Entities, UseCases, Presenters, DBAdapterJpa, and Application. Dependencies are configured for Spring Boot 2.1.0 (including starters for Web, JPA, Actuator, HATEOAS, and Validation), along with Swagger 2.9.2, H2, JUnit 4.12, Hamcrest 1.3, and Lombok 1.18.2.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 59 → 61 (+1.9)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 100 → 100 (+0.0)
- Architecture 69 → 88 (+18.7)
- Maturity 66 → 66 (+0.0)
- Readiness 41 → 50 (+9.2)
- Security 100 → 100 (+0.0)
- Domain Modelling 100 → 62 (-38.1)
Resolved (9)
- Coverage not included — suite not readable by the collector
- Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
- No exposed public API
- Test reliability not included
- The README does not state which programming languages or frameworks were used (Spring REST controllers, TDD framework) nor what databases/tables exist to connect the service. (README.md)
- early-stage repository — too little history to judge knowledge freshness
- git history depth insufficient
- git history depth insufficient
- single-maintainer — knowledge-concentration (bus factor) risk
New (22)
- Dependency hygiene PARTLY measured — Maven/Gradle declarations read, no dependency graph resolved
- Documentation: no installation or build instructions (README.md)
- No ADRs found
- No dependency advisory monitoring
- No direct assertions: can_cancel_offer (Application/src/test/java/com/grantburgess/application/EndpointTests.java)
- No direct assertions: can_create_offer (Application/src/test/java/com/grantburgess/application/EndpointTests.java)
- No direct assertions: can_get_offer_by_id (Application/src/test/java/com/grantburgess/application/EndpointTests.java)
- No direct assertions: can_get_offers (Application/src/test/java/com/grantburgess/application/EndpointTests.java)
- No direct assertions: can_get_offers (UseCases/src/test/java/com/grantburgess/ports/usescases/get/offers/GetOffersTest.java)
- No direct assertions: cancelled_offers_do_not_appear_in_list (UseCases/src/test/java/com/grantburgess/ports/usescases/get/offers/GetOffersTest.java)
- No direct assertions: cannot_add_offer_with_an_end_date_that_is_before_the_current_date (UseCases/src/test/java/com/grantburgess/ports/usescases/addoffer/AddOfferTest.java)
- No direct assertions: cannot_add_offer_with_same_name (UseCases/src/test/java/com/grantburgess/ports/usescases/addoffer/AddOfferTest.java)
- No direct assertions: cannot_cancel_offer_after_it_has_expired (UseCases/src/test/java/com/grantburgess/ports/usescases/canceloffer/CancelOfferTest.java)
- No direct assertions: cannot_cancel_offer_that_does_not_exist (UseCases/src/test/java/com/grantburgess/ports/usescases/canceloffer/CancelOfferTest.java)
- No direct assertions: cannot_cancel_offer_that_is_already_cancelled (UseCases/src/test/java/com/grantburgess/ports/usescases/canceloffer/CancelOfferTest.java)
- No direct assertions: cannot_get_cancelled_offer (UseCases/src/test/java/com/grantburgess/ports/usescases/get/offerbyid/GetOfferByIdTest.java)
- No direct assertions: cannot_get_offer_by_id_when_offer_does_not_exist (Application/src/test/java/com/grantburgess/application/EndpointTests.java)
- No direct assertions: cannot_get_offer_that_does_not_exist (UseCases/src/test/java/com/grantburgess/ports/usescases/get/offerbyid/GetOfferByIdTest.java)
- No direct assertions: expired_offers_have_the_status_expired (UseCases/src/test/java/com/grantburgess/ports/usescases/get/offers/GetOffersTest.java)
- No direct assertions: no_offers_returns_empty_response_list (UseCases/src/test/java/com/grantburgess/ports/usescases/get/offers/GetOffersTest.java)
- …and 2 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
grant-burgess/clean-architecture-example-java-spring-boot was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 351aabd8eb0aceb1ab9d10848d7599b01b20434b — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-fa71c66cabd8.