How miw-upm/apaw-practice works
1. This repository is a Spring Boot, Java, Maven application built as a layered teaching example. It is not a single business app; it contains many independent sample domains under one codebase, all following the same architecture.
2. The core architectural rule is one-way dependency flow: HTTP resources call domain services; domain services depend on domain persistence ports and domain models; MongoDB adapters implement those ports and map to storage entities. The domain layer stays separated from infrastructure concerns.
3. The API boundary lives in adapters/resources. Each business area has its own REST resource set, such as airport, bank, clinic, clothing store, football, music, recipes, recruiting, shop, sports academy, student council, university, vehicle, video website, videogame, warehouse, and winery. SystemResource provides a general system endpoint, and ApiExceptionHandler centralizes API error translation.
4. The business boundary lives in domain/services and domain/models. Every sample domain has its own service class set and its own model package, so each vertical slice is isolated rather than sharing a large generic model. Domain packages also contain enums, DTOs, and update/search helper objects when the use case needs them.
5. Persistence is abstracted through domain/persistenceports. These interfaces define what the domain needs from storage without binding it to MongoDB. This makes the domain layer portable and testable, and it explains the strong separation between “port” interfaces and concrete persistence implementations.
6. The MongoDB adapter layer is in adapters/mongodb. Each domain has its own subpackage with:
- Spring Data repositories in daos
- storage documents in entities
- MongoDB-based persistence adapters in persistence
- seeders to preload demo data
This layer is the concrete bridge between domain objects and MongoDB collections.
7. The data flow for a typical request is: REST resource receives the HTTP call, service applies business rules, service invokes a persistence port, the MongoDB adapter uses a repository to read/write entity documents, and the result is mapped back into a domain model and then into the API response. The same pattern repeats across all sample domains.
8. Seed data is part of the architecture, not an afterthought. Each domain has a dedicated seeder, and there is also a global DatabaseSeeder. This indicates the application is meant to run with reproducible demo datasets, especially in local and test environments.
9. The repo includes an outbound integration boundary in domain/restclients and adapters/restclients. UserRestClient/UserRestClientImpl represent calls to an external user service, so the application is not purely self-contained; at least one use case depends on another HTTP service.
10. Configuration and cross-cutting concerns are centralized in config. SecurityConfiguration, LoggingFilter, and RestTestConfiguration affect all modules, so they sit outside the domain slices and enforce application-wide behavior.
11. Testing is organized by architectural layer. There are service tests and service integration tests under domain/services, repository and persistence integration tests under adapters/mongodb, and functional tests for REST resources under functionaltests. That structure mirrors the runtime flow and validates each boundary separately.
12. The repository is built for containerized local execution and CI. Dockerfile, docker-compose.yml, and docker-compose-db.yml indicate a Docker-based runtime with MongoDB. GitHub Actions runs continuous integration, and SonarCloud is used for code quality gates, which are part of the project’s delivery pipeline.
Main entry points: services Services · resources REST API · mongodb MongoDB · persistenceports Ports
Components 18
Runtime
Bootstrapping and application-wide configuration
- Application · Starts the application and wires the layered architecture.
src/main/java/es/upm/miw/apaw/Application.java - Config · Security, logging, and test wiring applied across the app.
src/main/java/es/upm/miw/apaw/config
Adapters
HTTP and MongoDB boundaries plus the seeding bridge
- REST API · Resource layer exposing all sample business domains.
src/main/java/es/upm/miw/apaw/adapters/resources - Errors · Centralized translation of domain and infrastructure errors to HTTP responses.
src/main/java/es/upm/miw/apaw/adapters/resources/exceptionshandler - System · General endpoint outside the business slices.
src/main/java/es/upm/miw/apaw/adapters/resources/system/SystemResource.java - MongoDB · Concrete storage bridge for all vertical slices.
src/main/java/es/upm/miw/apaw/adapters/mongodb - Seeder · Global and per-domain seeders preload reproducible datasets.
src/main/java/es/upm/miw/apaw/adapters/mongodb/DatabaseSeeder.java
Domain
Business services, models, and persistence ports
- Airport · Representative sample domain with its own resources, services, models, and Mongo adapters.
src/main/java/es/upm/miw/apaw/domain/services/airport - Commerce · Representative group for bank, clinic, clothing store, shop, and recruiting-style business examples.
src/main/java/es/upm/miw/apaw/domain/services - Mobility · Representative group for metro, vehicle, warehouse, and transport-style examples.
src/main/java/es/upm/miw/apaw/domain/services/metro - Media · Representative group for music, video website, and videogame examples.
src/main/java/es/upm/miw/apaw/domain/services/music - Sports · Representative group for football, fighters, martial arts gym, and sports academy examples.
src/main/java/es/upm/miw/apaw/domain/services/sports - Education · Representative group for university and student council examples.
src/main/java/es/upm/miw/apaw/domain/services/university - Services · Business logic layer coordinating rules and repository access across independent slices.
src/main/java/es/upm/miw/apaw/domain/services - Models · Per-slice entities, DTOs, enums, and update/search helper objects.
src/main/java/es/upm/miw/apaw/domain/models - Ports · Storage abstractions implemented by adapters and kept free of MongoDB concerns.
src/main/java/es/upm/miw/apaw/domain/persistenceports
Integration
Outbound HTTP dependency
- User client · Domain-facing contract for the external user service.
src/main/java/es/upm/miw/apaw/domain/restclients/UserRestClient.java - User client impl · Concrete REST client implementation used by the application.
src/main/java/es/upm/miw/apaw/adapters/restclients/UserRestClientImpl.java
Connections 18
- Application → Config: loads · Bootstrapping activates application-wide configuration.
- Application → REST API: starts · Spring Boot exposes the REST resources.
- REST API → Errors: uses · Resources rely on centralized error translation.
- REST API → Services: calls · HTTP resources delegate to use-case services.
- Services → Models: uses · Services operate on domain objects and DTOs.
- Services → Ports: depends on · Services access storage only through ports.
- MongoDB → Ports: implements · MongoDB adapters fulfill the domain contracts.
- MongoDB → Seeder: bootstraps · Seeders populate demo data through the adapter layer.
- Seeder → MongoDB: writes via · Seed data is inserted using MongoDB persistence infrastructure.
- Models → Ports: shapes · Models define the data expected by ports and services.
- Airport → Services: example of · One representative vertical slice in the layered pattern.
- Commerce → Services: example of · Representative business-domain cluster.
- Mobility → Services: example of · Representative transport and logistics cluster.
- Media → Services: example of · Representative content and media cluster.
- Sports → Services: example of · Representative sports-related cluster.
- Education → Services: example of · Representative education-related cluster.
- User client impl → User client: implements · Concrete adapter fulfills the outbound contract.
- Services → User client: calls · Selected use cases depend on external user data.