--- name: spring-modulith-verifier description: > Verifies whether code follows Spring Modulith code structure or not. Show list of violations along with recommendations on how to fix them. Use this skill: * When reviewing Spring Boot applications which uses Spring Modulith * When verifying whether Spring Boot application code follows Spring Modulith package structure --- # Spring Modulith Verifier Skill Use a **domain-driven, modular layout**: organize packages by **business modules**, not by technical layers. ### Recommended Example Package Structure ``` dev.sivalabs.projectname/ ├── Application # Main Spring Boot entrypoint class ├── shared/ # Cross-cutting concerns │ ├── package-info.java ├── users/ # Users module (bounded context) │ ├── config/ # Users module-specific config │ ├── domain/ # Domain logic │ │ ├── models/ # Domain models │ │ │ ├── package-info.java │ │ ├── exceptions/ # Domain custom Exception classes │ │ │ ├── package-info.java │ │ ├── {entities, repositories, mappers, services} │ ├── api/ # REST API layer │ │ ├── {controllers, DTOs} # REST controllers, Request, Response payload DTOs │ └── UsersAPI.java # Module's public API (facade) │ ├── catalog/ # Catalog module ├── orders/ # Orders module └── config/ # Global Configuration └── WebMvcConfig.java └── SecurityConfig.java └── WebSecurityConfig.java └── GlobalExceptionHandler.java ``` Explanation of the above package structure: - **Application.java**: The main Spring Boot entry point class annotated with `@SpringBootApplication`. Contains the `main()` method that bootstraps the application. - **shared/**: Contains cross-cutting concerns and utilities shared across multiple modules (e.g., common utilities, shared DTOs, base classes, custom annotations). - **{module}/** (e.g., users/, catalog/, orders/): Each business module represents a bounded context and contains: - **config/**: Module-specific configuration classes annotated with `@Configuration` for beans, properties, or third-party integrations relevant only to this module. - **domain/**: Core business logic layer containing: - **models/**: Domain model classes (Command, Query objects, Enums, Value Objects, Result objects, etc) representing business concepts (not JPA entities). These are pure Java objects that encapsulate business rules. - **exceptions/**: Domain specific custom Exception classes. - **entities**: JPA entity classes annotated with `@Entity` that map to database tables. These should not be `public` to prevent direct instantiation and ensure encapsulation. - **repositories**: Spring Data JPA repository interfaces extending `JpaRepository` or `CrudRepository` for data access. These should not be `public`. - **mappers**: Mapper classes/interfaces (e.g., MapStruct mappers) for converting between entities, domain models, and DTOs. These should not be `public`. - **services**: Service classes annotated with `@Service` containing business logic, converting beans using mappers, transaction management, and orchestration of repository calls. - **api/**: REST API layer containing: - **controllers**: REST controller classes annotated with `@RestController` that handle HTTP requests, validate input, and delegate to services. - **DTOs**: Data Transfer Objects including request payloads (data coming from clients) and response payloads (data sent to clients). - **{Module}API.java**: A facade class that serves as the module's public API, delegating calls to services, exposing only what other modules should access while hiding internal implementation details. - **config/**: Global application-wide configuration classes including: - **WebMvcConfig.java**: MVC configuration (CORS, interceptors, formatters). - **SecurityConfig.java**: Spring Security configuration for authentication and authorization. - **GlobalExceptionHandler.java**: Centralized exception handling using `@RestControllerAdvice` for consistent error responses. ### Visibility Modifiers Default to **minimum necessary visibility**. Only expose what other modules or layers genuinely need. | Component | Class | Constructor | Methods | |--------------------------|-----------------------------|-----------------|-----------------| | Controller | package-private | package-private | package-private | | Service | `public` | package-private | `public` | | Repository | package-private (interface) | — | — | | Entity | package-private | protected | `public` | | DTO / record | `public` or package-private | — | — | | Module API facade | `public` | package-private | `public` | | Request/Response records | package-private | — | — | | Config/Exception handler | package-private | — | — | ### Naming Conventions | Type | Convention | Example | |-----------------------|----------------------|-------------------------------------------------------------| | **Entities** | `*Entity` | `UserEntity`, `AddressEntity` | | **Value Objects** | Domain name (record) | `Email`, `UserCode`, `UserId` | | **Commands** | `*Cmd` | `CreateUserCmd`, `UpdateAddressCmd` | | **Command Response** | `*Result` | `LoginResult`, `RegistrationResult` | | **DTOs** | `*Dto` | `UserDto`, `AddressDto` | | **HTTP Request** | `*Request` | `CreateUserRequest`, `CreateAddressRequest` | | **HTTP Response** | `*Response` | `CreateUserResponse`, `CreateAddressResponse` | | **Repositories** | `*Repository` | `UserRepository`, `AddressBookRepository` | | **Services** | `*Service` | `UserService`, `AddressBookService` | | **Domain Exceptions** | `*Exception` | `InvalidUserCreationException`, `UserCancellationException` | | **Module API** | `*API` | `UsersAPI` |