Skip to content
CAI
Software that uses CAICheck a score

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

CAI band scale
CAI trend line
CAI lens gauges

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.