Spring Boot

Estrutura e prática Spring Boot framework

Resumo em construção
Voltar

Material complementar:

  • Conteúdo no GitHub: Acesse
  • Curso com certificado na Workover Academy (Criar API REST Spring Boot com Kotlin): Acesse

Conceito:

Camada que atua sob framework Spring, simplificando-o e modernizando-o, seguindo padrão MVC. Spring implementa padrão IoC (Inversion of Control), onde os objetos (Spring Beans / Beans) são instanciados automaticamente pelo container do Spring, dispensando criação manual.


Pré-requisitos (Windows):

JDK (Java Development Kit) é kit de ferramentas e bibliotecas para desenvolver aplicações Java. Gradle é automatizador de build moderno que usa linguagem baseada em Groovy ou Kotlin para configurar projetos.

  1. JDK: Acesse
    1. Baixar e instalar JDK Oracle
    2. Win + R, digite "SystemPropertiesAdvanced", acessar Variáveis de Ambiente
    3. Aba "Variáveis do sistema", em Novo, criar/editar variáveis:
        Criar:
      • Nome: JAVA_HOME
      • Valor: Caminho da pasta com JDK instalado (Ex: "C:\Program Files\Java\jdk-24")
      • Confirmar criação OK

      • Editar:
      • Nome: Path
      • Clicar em Novo
      • Valor: %JAVA_HOME%\bin
      • Confirmar criação OK
    4. Verificar instalação no CMD, com comando "java -version"
  2. Kotlin compiler: Acesse
    1. Baixar e instalar Kotlin compiler (.zip)
    2. Diretório "C:/", crie pasta "Kotlin", e descompacte o Kotlin dentro dela
    3. Win + R, digite "SystemPropertiesAdvanced", acessar Variáveis de Ambiente
    4. Aba "Variáveis do sistema", editar variável Path: Editar:
      • Nome: Path
      • Clicar em Novo
      • Valor: C:\Kotlin\kotlinc\bin
      • Confirmar criação OK
    5. Verificar instalação: Win + R, digitar CMD, e informar comando "kotlinc -version"
  3. Gradle: Acesse
    1. Baixar e instalar Gradle: site oficial Gradle, Install, Install manually, Step 1, baixar Binary-only
    2. Diretório "C:/", crie pasta "Gradle", e descompacte o Gradle dentro dela
    3. Win + R, digite "SystemPropertiesAdvanced", acessar Variáveis de Ambiente
    4. Aba "Variáveis do sistema", editar variável Path: Editar:
      • Nome: Path
      • Clicar em Novo
      • Valor: C:\Gradle\gradle-VERSAO\bin
      • Confirmar criação OK
    5. Verificar instalação: Win + R, digitar CMD, e informar comando "gradle -v"

Criar projeto:

Em 'start.spring.io', selecione:

  1. Project: Gradle - Kotlin
  2. Language: Kotlin
  3. Spring Boot: 3.5.13
  4. Group: com.seuprojeto
  5. Artifact: nomeProjeto
  6. Package name: com.seuprojeto.nomeProjeto
  7. Packaging: Jar
  8. Configuration: YAML
  9. Java: 21
  10. Dependencies:
    • Spring Web
    • Spring Data JPA
    • Validation
    • Spring Boot Dev Tools
  11. Generate (extrair zip e acessar projeto com IntelliJ)

Layer-based Structure:

Estrutura tradicional/standard (Structure/Package by Layer), onde cada camada (Controller, Service, Repository) é organizada em pacotes separados. Melhor cenário: sistemas mais simples, bem estruturados, com responsabilidades claras (como em CRUDs). Pior cenário: pouca flexibilidade para mudanças, acoplamento entre camadas e dificuldade em evoluir o domínio:


com.company.project
├── ProjectApplication.java
├── config
│   ├── SecurityConfig.java
│   ├── DatabaseConfig.java
│   └── SwaggerConfig.java
├── controller
│   ├── UserController.java
│   └── ProductController.java
├── service
│   ├── UserService.java
│   ├── UserServiceImpl.java
│   ├── ProductService.java
│   └── ProductServiceImpl.java
├── repository
│   ├── UserRepository.java
│   └── ProductRepository.java
├── model
│   ├── entity
│   │   ├── User.java
│   │   └── Product.java
│   └── dto
│       ├── UserDTO.java
│       ├── CreateUserRequest.java
│       └── ProductDTO.java
├── exception
│   ├── GlobalExceptionHandler.java
│   ├── ResourceNotFoundException.java
│   └── ValidationException.java
├── mapper
│   ├── UserMapper.java
│   └── ProductMapper.java
├── security
│   ├── JwtTokenProvider.java
│   └── CustomUserDetailsService.java
└── util
    ├── DateUtil.java
    └── ValidationUtil.java

src/main/resources:


resources
├── application.yml
├── application-dev.yml
├── application-prod.yml
├── static
│   └── (static files)
├── templates
│   └── (template files)
└── db
    └── migration
        ├── V1__Create_users_table.sql
        └── V2__Add_products_table.sql

src/test:


src/test/java/com/company/project
├── controller
│   └── UserControllerTest.java
├── service
│   └── UserServiceTest.java
└── repository
    └── UserRepositoryTest.java

Layer-based Structure com módulos em pacotes:

Arquitetura anterior, onde projeto é organizado em módulos via pacotes, que seguem a estrutura de camadas tradicional (controller/seevice/repository/model):


com.whateverer.config
 ├── SwaggerConfig.kt
 ├── SecurityConfig.kt
 ├── JwtConfig.kt
 ├── OpenApiConfig.kt
 ├── JacksonConfig.kt
 ├── CorsConfig.kt
 ├── DatabaseConfig.kt
 ├── CacheConfig.kt
 └── WebMvcConfig.kt

com.whateverer.feature.account
 ├── controller
 │     ├── AccountController.kt
 │     ├── AccountAdminController.kt
 │     └── AccountAuthController.kt
 │
 ├── model
 │     ├── dto
 │     │     ├── CreateAccountRequest.kt
 │     │     ├── UpdateAccountRequest.kt
 │     │     ├── AccountResponse.kt
 │     │     ├── AccountSummaryResponse.kt
 │     │     └── AccountLoginRequest.kt
 │     │
 │     └── entity
 │           ├── AccountEntity.kt
 │           ├── AccountProfileEntity.kt
 │           ├── AccountRoleEntity.kt
 │           └── AccountStatus.kt
 │
 ├── repository
 │     ├── AccountRepository.kt
 │     ├── AccountQueryRepository.kt
 │     └── AccountCustomRepository.kt
 │
 ├── service
 │     ├── AccountService.kt
 │     ├── CreateAccountService.kt
 │     ├── UpdateAccountService.kt
 │     ├── DeleteAccountService.kt
 │     ├── GetAccountService.kt
 │     ├── ListAccountService.kt
 │     ├── AccountValidationService.kt
 │     └── AccountAuthService.kt
 │
 └── utils
       ├── AccountMapper.kt
       ├── AccountUtils.kt
       ├── AccountValidator.kt
       ├── AccountConstants.kt
       └── AccountPermissions.kt

com.whateverer.feature.payment
 ├── controller
 │     ├── PaymentController.kt
 │     ├── RefundController.kt
 │     └── PaymentWebhookController.kt
 │
 ├── model
 │     ├── dto
 │     │     ├── CreatePaymentRequest.kt
 │     │     ├── PaymentResponse.kt
 │     │     ├── RefundRequest.kt
 │     │     ├── PaymentStatusResponse.kt
 │     │     └── InstallmentSimulationResponse.kt
 │     │
 │     └── entity
 │           ├── PaymentEntity.kt
 │           ├── RefundEntity.kt
 │           ├── PaymentMethodEntity.kt
 │           └── PaymentStatus.kt
 │
 ├── repository
 │     ├── PaymentRepository.kt
 │     ├── RefundRepository.kt
 │     └── PaymentQueryRepository.kt
 │
 ├── service
 │     ├── PaymentService.kt
 │     ├── RefundService.kt
 │     ├── PaymentGatewayService.kt
 │     ├── PaymentValidationService.kt
 │     ├── InstallmentService.kt
 │     └── PaymentWebhookService.kt
 │
 └── utils
       ├── PaymentMapper.kt
       ├── PaymentUtils.kt
       ├── PaymentValidator.kt
       ├── PaymentConstants.kt
       └── InstallmentCalculator.kt

Feature-based Structure:

Estrutura moderna (Structure/Package by Feature), onde cada feature/recurso é organizada em pacotes separados, sendo ideal para projetos complexos, escaláveis e microservices. Melhor cenário: sistemas grandes, com várias funcionalidades, onde cada módulo agrupa lógica, testes e regras relacionadas. Pior cenário: pode gerar duplicação de código se não for bem estruturado, e o time precisa se organizar para manter o alinhamento entre features:


com.myapp.project
 ├── Application.java
 ├── user/
 │     ├── UserController.java
 │     ├── UserService.java
 │     ├── UserRepository.java
 │     ├── User.java (entity)
 │     ├── UserDto.java
 ├── product/
 │     ├── ProductController.java
 │     ├── ProductService.java
 │     ├── ProductRepository.java
 │     ├── Product.java
 │     ├── ProductDto.java
 ├── auth/
 │     ├── AuthController.java
 │     ├── AuthService.java
 │     ├── JwtService.java
 │     ├── JwtAuthenticationFilter.java
 │     ├── CustomUserDetailsService.java
 │     ├── LoginRequest.java
 │     ├── RegisterRequest.java
 │     ├── AuthResponse.java
 │     └── JwtUtil.java
 ├── config/
 │     ├── AppConfig.java
 │     ├── SecurityConfig.java
 │     ├── DatabaseConfig.java
 │     ├── SwaggerConfig.java
 │     └── JwtConfig.java
 ├── exception/
 │     ├── GlobalExceptionHandler.java
 │     ├── ResourceNotFoundException.java
 │     ├── ValidationException.java
 │     ├── UnauthorizedException.java
 │     ├── InvalidTokenException.java
 │     └── TokenExpiredException.java
 ├── mapper/
 │     ├── UserMapper.java
 │     └── ProductMapper.java
 └── util/
       ├── DateUtil.java
       ├── ValidationUtil.java
       └── PasswordUtil.java

src/main/resources:


resources
├── application.yml
├── application-dev.yml
├── application-prod.yml
├── static
│   └── (static files, css, js, images)
├── templates
│   └── (template files, html, thymeleaf)
├── config
│   ├── security.yml
│   ├── swagger.yml
│   ├── e.g. application.yml
│   ├── logging.yml
│   └── database.ym
└── db
    └── migration
        ├── V1__Create_users_table.sql
        └── V2__Add_products_table.sql

src/test:


src/test/java/com/myapp/project
├── user/
│     ├── UserControllerTest.java
│     ├── UserServiceTest.java
│     └── UserRepositoryTest.java
├── product/
│     ├── ProductControllerTest.java
│     ├── ProductServiceTest.java
│     └── ProductRepositoryTest.java
└── config/
    └── SecurityConfigTest.java

Hexagonal Architecture:

Arquitetura moderna (Hexagonal Architecture / Ports and Adapters), onde a aplicação é organizada em camadas concêntricas, com o domínio central isolado de detalhes de infraestrutura, sendo ideal para projetos complexos, escaláveis e microservices. Melhor cenário: sistemas complexos, com alto desacoplamento, onde o domínio é protegido de detalhes externos, permitindo fácil troca de tecnologia e alta testabilidade. Pior cenário: curva de aprendizado mais alta, abstrações adicionais, exigindo mais esforço para implementar no início:


src/main/java/com/myapp/project
├── application/
│   ├── port/
│   │   ├── input/
│   │   │   ├── UserUseCase.java
│   │   │   └── ProductUseCase.java
│   │   └── output/
│   │       ├── UserPersistencePort.java
│   │       └── ProductPersistencePort.java
│   ├── service/
│   │   ├── UserServiceImpl.java
│   │   └── ProductServiceImpl.java
│   ├── dto/
│   │   ├── UserDto.java
│   │   └── ProductDto.java
│   └── mapper/
│       ├── UserMapper.java
│       └── ProductMapper.java
├── domain/
│   ├── model/
│   │   ├── User.java
│   │   └── Product.java
│   ├── exception/
│   │   ├── ResourceNotFoundException.java
│   │   ├── ValidationException.java
│   │   ├── UnauthorizedException.java
│   │   ├── InvalidTokenException.java
│   │   └── TokenExpiredException.java
│   └── vo/
│       └── (Value Objects opcionais)
├── infrastructure/
│   ├── input/
│   │   ├── rest/
│   │   │   ├── UserController.java
│   │   │   └── ProductController.java
│   │   └── config/
│   │       ├── SwaggerConfig.java
│   │       └── SecurityConfig.java
│   └── output/
│       ├── persistence/
│       │   ├── UserRepositoryImpl.java
│       │   └── ProductRepositoryImpl.java
│       ├── security/
│       │   ├── JwtTokenProvider.java
│       │   └── CustomUserDetailsService.java
│       └── config/
│           └── DatabaseConfig.java
├── shared/
│   └── exception/
│       └── GlobalExceptionHandler.java
└── Application.java

Modular Monolith + Clean Architecture + DDD:

Arquitetura profissional moderna (Modular Monolith + Clean Architecture + DDD), onde aplicação é organizada em módulos independentes, seguindo princípios de Clean Architecture e Domain-Driven Design, sendo ideal para projetos complexos, escaláveis e microservices. Melhor cenário: sistemas complexos, com alto desacoplamento, onde o domínio é protegido de detalhes externos, permitindo fácil evolução do domínio e alta testabilidade. Pior cenário: curva de aprendizado mais alta, abstrações adicionais, exigindo mais esforço para implementar no início:


my-erp-system/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle.properties
├── docker-compose.yml
├── Dockerfile
├── README.md
├── .gitignore
├── .editorconfig
├── .env
│
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
│
├── docs/
│   ├── architecture/
│   │   ├── context-diagram.md
│   │   ├── containers-diagram.md
│   │   ├── components-diagram.md
│   │   ├── domain-overview.md
│   │   ├── bounded-contexts.md
│   │   └── decisions/
│   │       ├── adr-001-modular-monolith.md
│   │       ├── adr-002-clean-architecture.md
│   │       └── adr-003-ddd.md
│   │
│   ├── api/
│   │   ├── openapi.yaml
│   │   └── postman-collection.json
│   │
│   └── database/
│       ├── schema.drawio
│       └── migrations.md
│
├── scripts/
│   ├── start-local.sh
│   ├── build.sh
│   ├── deploy.sh
│   └── test.sh
│
├── src/
│   ├── main/
│   │   ├── kotlin/
│   │   │   └── com/
│   │   │       └── company/
│   │   │           └── erp/
│   │   │               │
│   │   │               ├── ErpApplication.kt
│   │   │               │
│   │   │               ├── shared/
│   │   │               │   │
│   │   │               │   ├── kernel/
│   │   │               │   │   ├── domain/
│   │   │               │   │   │   ├── AggregateRoot.kt
│   │   │               │   │   │   ├── Entity.kt
│   │   │               │   │   │   ├── ValueObject.kt
│   │   │               │   │   │   ├── DomainEvent.kt
│   │   │               │   │   │   ├── Identifier.kt
│   │   │               │   │   │   └── AuditableEntity.kt
│   │   │               │   │   │
│   │   │               │   │   ├── application/
│   │   │               │   │   │   ├── UseCase.kt
│   │   │               │   │   │   ├── Command.kt
│   │   │               │   │   │   ├── Query.kt
│   │   │               │   │   │   ├── CommandHandler.kt
│   │   │               │   │   │   ├── QueryHandler.kt
│   │   │               │   │   │   └── EventPublisher.kt
│   │   │               │   │   │
│   │   │               │   │   ├── infrastructure/
│   │   │               │   │   │   ├── BaseEntity.kt
│   │   │               │   │   │   ├── BaseRepository.kt
│   │   │               │   │   │   ├── JpaConfig.kt
│   │   │               │   │   │   └── TransactionConfig.kt
│   │   │               │   │   │
│   │   │               │   │   └── exception/
│   │   │               │   │       ├── BusinessException.kt
│   │   │               │   │       ├── ValidationException.kt
│   │   │               │   │       ├── NotFoundException.kt
│   │   │               │   │       └── DomainException.kt
│   │   │               │   │
│   │   │               │   ├── config/
│   │   │               │   │   ├── JacksonConfig.kt
│   │   │               │   │   ├── SecurityConfig.kt
│   │   │               │   │   ├── OpenApiConfig.kt
│   │   │               │   │   ├── CacheConfig.kt
│   │   │               │   │   ├── KafkaConfig.kt
│   │   │               │   │   └── ClockConfig.kt
│   │   │               │   │
│   │   │               │   ├── security/
│   │   │               │   │   ├── JwtService.kt
│   │   │               │   │   ├── JwtAuthenticationFilter.kt
│   │   │               │   │   ├── UserPrincipal.kt
│   │   │               │   │   └── AuthenticatedUser.kt
│   │   │               │   │
│   │   │               │   ├── observability/
│   │   │               │   │   ├── LoggingInterceptor.kt
│   │   │               │   │   ├── MetricsConfig.kt
│   │   │               │   │   ├── TracingConfig.kt
│   │   │               │   │   └── CorrelationIdFilter.kt
│   │   │               │   │
│   │   │               │   ├── messaging/
│   │   │               │   │   ├── InternalEventBus.kt
│   │   │               │   │   ├── KafkaEventPublisher.kt
│   │   │               │   │   └── EventSerializer.kt
│   │   │               │   │
│   │   │               │   └── web/
│   │   │               │       ├── ApiErrorResponse.kt
│   │   │               │       ├── GlobalExceptionHandler.kt
│   │   │               │       ├── PaginationRequest.kt
│   │   │               │       └── PaginationResponse.kt
│   │   │               │
│   │   │               ├── modules/
│   │   │               │
│   │   │               │   ├── customer/
│   │   │               │   │   │
│   │   │               │   │   ├── domain/
│   │   │               │   │   │   ├── model/
│   │   │               │   │   │   │   ├── Customer.kt
│   │   │               │   │   │   │   ├── CustomerAddress.kt
│   │   │               │   │   │   │   ├── CustomerDocument.kt
│   │   │               │   │   │   │   ├── CustomerStatus.kt
│   │   │               │   │   │   │   └── CustomerId.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   ├── event/
│   │   │               │   │   │   │   ├── CustomerCreatedEvent.kt
│   │   │               │   │   │   │   ├── CustomerUpdatedEvent.kt
│   │   │               │   │   │   │   └── CustomerDeletedEvent.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   ├── service/
│   │   │               │   │   │   │   ├── CustomerDomainService.kt
│   │   │               │   │   │   │   └── CustomerValidationService.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   └── repository/
│   │   │               │   │   │       └── CustomerRepository.kt
│   │   │               │   │   │
│   │   │               │   │   ├── application/
│   │   │               │   │   │   ├── usecase/
│   │   │               │   │   │   │   ├── createcustomer/
│   │   │               │   │   │   │   │   ├── CreateCustomerCommand.kt
│   │   │               │   │   │   │   │   ├── CreateCustomerUseCase.kt
│   │   │               │   │   │   │   │   ├── CreateCustomerResponse.kt
│   │   │               │   │   │   │   │   └── CreateCustomerValidator.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   ├── updatecustomer/
│   │   │               │   │   │   │   │   ├── UpdateCustomerCommand.kt
│   │   │               │   │   │   │   │   ├── UpdateCustomerUseCase.kt
│   │   │               │   │   │   │   │   └── UpdateCustomerValidator.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   ├── getcustomer/
│   │   │               │   │   │   │   │   ├── GetCustomerQuery.kt
│   │   │               │   │   │   │   │   ├── GetCustomerUseCase.kt
│   │   │               │   │   │   │   │   └── CustomerDetailsResponse.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   ├── listcustomers/
│   │   │               │   │   │   │   │   ├── ListCustomersQuery.kt
│   │   │               │   │   │   │   │   ├── ListCustomersUseCase.kt
│   │   │               │   │   │   │   │   └── CustomerSummaryResponse.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   └── deletecustomer/
│   │   │               │   │   │   │       ├── DeleteCustomerCommand.kt
│   │   │               │   │   │   │       └── DeleteCustomerUseCase.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   ├── port/
│   │   │               │   │   │   │   ├── input/
│   │   │               │   │   │   │   │   ├── CreateCustomerInputPort.kt
│   │   │               │   │   │   │   │   ├── UpdateCustomerInputPort.kt
│   │   │               │   │   │   │   │   └── GetCustomerInputPort.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   └── output/
│   │   │               │   │   │   │       ├── LoadCustomerPort.kt
│   │   │               │   │   │   │       ├── SaveCustomerPort.kt
│   │   │               │   │   │   │       └── DeleteCustomerPort.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   ├── mapper/
│   │   │               │   │   │   │   ├── CustomerMapper.kt
│   │   │               │   │   │   │   └── CustomerResponseMapper.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   └── eventhandler/
│   │   │               │   │   │       └── CustomerCreatedEventHandler.kt
│   │   │               │   │   │
│   │   │               │   │   ├── infrastructure/
│   │   │               │   │   │   ├── persistence/
│   │   │               │   │   │   │   ├── entity/
│   │   │               │   │   │   │   │   ├── CustomerJpaEntity.kt
│   │   │               │   │   │   │   │   └── CustomerAddressEmbeddable.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   ├── repository/
│   │   │               │   │   │   │   │   ├── JpaCustomerRepository.kt
│   │   │               │   │   │   │   │   └── SpringDataCustomerRepository.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   └── mapper/
│   │   │               │   │   │   │       ├── CustomerJpaMapper.kt
│   │   │               │   │   │   │       └── CustomerEntityMapper.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   ├── web/
│   │   │               │   │   │   │   ├── CustomerController.kt
│   │   │               │   │   │   │   ├── request/
│   │   │               │   │   │   │   │   ├── CreateCustomerRequest.kt
│   │   │               │   │   │   │   │   └── UpdateCustomerRequest.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   └── response/
│   │   │               │   │   │   │       ├── CustomerResponse.kt
│   │   │               │   │   │   │       └── CustomerListResponse.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   ├── messaging/
│   │   │               │   │   │   │   ├── consumer/
│   │   │               │   │   │   │   │   └── CustomerEventConsumer.kt
│   │   │               │   │   │   │   │
│   │   │               │   │   │   │   └── producer/
│   │   │               │   │   │   │       └── CustomerEventProducer.kt
│   │   │               │   │   │   │
│   │   │               │   │   │   └── config/
│   │   │               │   │   │       └── CustomerModuleConfig.kt
│   │   │               │   │   │
│   │   │               │   │   └── CustomerModule.kt
│   │   │               │   │
│   │   │               │   ├── order/
│   │   │               │   │   ├── domain/
│   │   │               │   │   ├── application/
│   │   │               │   │   ├── infrastructure/
│   │   │               │   │   └── OrderModule.kt
│   │   │               │   │
│   │   │               │   ├── payment/
│   │   │               │   │   ├── domain/
│   │   │               │   │   ├── application/
│   │   │               │   │   ├── infrastructure/
│   │   │               │   │   └── PaymentModule.kt
│   │   │               │   │
│   │   │               │   ├── inventory/
│   │   │               │   │   ├── domain/
│   │   │               │   │   ├── application/
│   │   │               │   │   ├── infrastructure/
│   │   │               │   │   └── InventoryModule.kt
│   │   │               │   │
│   │   │               │   └── auth/
│   │   │               │       ├── domain/
│   │   │               │       ├── application/
│   │   │               │       ├── infrastructure/
│   │   │               │       └── AuthModule.kt
│   │   │               │
│   │   │               └── bootstrap/
│   │   │                   ├── DatabaseSeeder.kt
│   │   │                   ├── ModuleRegistrar.kt
│   │   │                   └── StartupRunner.kt
│   │   │
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── application-dev.yml
│   │       ├── application-test.yml
│   │       ├── application-prod.yml
│   │       │
│   │       ├── db/
│   │       │   └── migration/
│   │       │       ├── V1__create_customer_table.sql
│   │       │       ├── V2__create_order_table.sql
│   │       │       ├── V3__create_payment_table.sql
│   │       │       └── V4__create_inventory_table.sql
│   │       │
│   │       ├── banner.txt
│   │       ├── logback-spring.xml
│   │       └── messages/
│   │           ├── messages.properties
│   │           └── validation.properties
│   │
│   └── test/
│       └── kotlin/
│           └── com/
│               └── company/
│                   └── erp/
│                       ├── integration/
│                       │   ├── CustomerIntegrationTest.kt
│                       │   ├── OrderIntegrationTest.kt
│                       │   └── PaymentIntegrationTest.kt
│                       │
│                       ├── unit/
│                       │   ├── customer/
│                       │   │   ├── domain/
│                       │   │   ├── application/
│                       │   │   └── infrastructure/
│                       │   │
│                       │   ├── order/
│                       │   └── payment/
│                       │
│                       ├── architecture/
│                       │   ├── ModularizationTest.kt
│                       │   ├── LayerDependencyTest.kt
│                       │   ├── HexagonalRulesTest.kt
│                       │   └── DddConventionsTest.kt
│                       │
│                       └── e2e/
│                           ├── CustomerFlowE2ETest.kt
│                           └── OrderFlowE2ETest.kt
│
└── .github/
    └── workflows/
        ├── ci.yml
        ├── cd.yml
        └── code-quality.yml

Funcionamento:

Baseado na arquitetura Layer-based Structure com módulos.


resources
 ├── application.yml # Configurações gerais da aplicação, como porta, datasource, logging, etc.
 ├── application-dev.yml # Configurações específicas para ambiente de desenvolvimento, como banco de dados local, logging detalhado, etc.
 ├── application-prod.yml # Configurações específicas para ambiente de produção, como banco de dados em nuvem, logging otimizado, etc.
 ├── static # Diretório com arquivos estáticos, como CSS, JavaScript e imagens, usados para servir conteúdo estático (se aplicável)
 ├── templates # Diretório com arquivos de template, como HTML ou Thymeleaf, usados para renderizar páginas (se aplicável)
 └── db # Scripts de banco de dados, como migrações SQL ou arquivos de configuração do Flyway/Liquibase
     └── migration # Scripts de migração do banco de dados, nomeados seguindo convenção (V1__create_users_table.sql, V2__add_products_table.sql, etc.)
         ├── V1__create_users_table.sql # Exemplo de script de migração para criar tabela de usuários
         └── V2__add_products_table.sql # Exemplo de script de migração para adicionar tabela de produtos

com.whateverer.config # Configurações globais
 ├── SwaggerConfig.kt # Configuração do Swagger para documentação da API
 ├── SecurityConfig.kt # Configuração de segurança, incluindo autenticação, autorização, filtros de segurança e rotas públicas/privadas
 ├── JwtConfig.kt # Configuração específica para JWT (JSON Web Token), como geração e validação de tokens, além de expiração e assinatura
 ├── OpenApiConfig.kt # Configuração da documentação OpenAPI, contendo título da API, versão, descrição e autenticação JWT no Swagger
 ├── JacksonConfig.kt # Configuração do serializer/deserializer JSON do Jackson, que converte Kotlin objects para JSON e vice-versa, como formatos de datas, null handling
 ├── CorsConfig.kt # Configuração de CORS (Cross-Origin Resource Sharing), definindo quais domínios podem acessar a API (como frontend), métodos HTTP permitidos e cabeçalhos
 ├── DatabaseConfig.kt # Configuração do banco de dados, incluindo conexão, datasource, JPA/Hibernate, pool de conexões, transações e demais propriedades de acesso ao banco
 ├── CacheConfig.kt # Configuração de cache, definindo quais dados devem ser armazenados em cache, tempo de expiração e estratégia de cache (como Redis, cache local ou Caffeine) para otimização de desempenho e redução de queries
 └── WebMvcConfig.kt # Configuração do Spring MVC (Model-View-Controller), incluindo resolvers, interceptors, formatadores, conversores, manipuladores de exceção e outras customizações relacionadas ao comportamento da camada web geral

com.whateverer.feature.account # Funcionalidades relacionadas ao domínio de gestão de contas e usuários
 ├── controller # Camada de controle, responsável por receber requisições HTTP REST, validar dados de entrada, chamar os serviços e retornar respostas adequadas
 │     ├── AccountController.kt # Controlador para endpoints principais de conta (criar, obter, atualizar, excluir)
 │     ├── AccountAdminController.kt # Controlador para endpoints administrativos de conta (listar contas, alterar status, atribuir papéis, bloquear contas)
 │     └── AccountAuthController.kt # Controlador para endpoints de autenticação e autorização (login, logout, refresh token)
 │
 ├── model # Camada de modelo, contendo definições de dados usados na aplicação, como DTOs (Data Transfer Objects) para comunicação entre camadas e entidades JPA para persistência no banco de dados
 │     ├── dto # Pacote de DTOs, objetos usados para transferir dados entre camadas em comunicação HTTP, como requisições e respostas da API
 │     │     ├── CreateAccountRequest.kt # Dados recebidos ao criar conta
 │     │     ├── UpdateAccountRequest.kt # Dados recebidos ao atualizar conta
 │     │     ├── AccountResponse.kt # Dados retornados/resposta ao obter detalhes de conta
 │     │     ├── AccountSummaryResponse.kt # Dados retornados/resumo ao listar contas
 │     │     └── AccountLoginRequest.kt # Payload, dados recebidos ao realizar login
 │     │
 │     └── entity # Pacote de entidades, classes que representam tabelas do banco de dados usando JPA/Hibernate, contendo anotações de mapeamento e relacionamentos
 │           ├── AccountEntity.kt # Entidade principal de conta, representando tabela principal de contas no banco de dados
 │           ├── AccountProfileEntity.kt # Entidade de perfil de conta, representando informações adicionais do usuário, como nome, email, telefone
 │           ├── AccountRoleEntity.kt # Entidade de papel de conta, representando os papéis/roles/permissões atribuídos a cada conta para controle de acesso (admin, user)
 │           └── AccountStatus.kt # Enumeração de status de conta, representando possíveis estados de conta (ativa, inativa, bloqueada, etc.)
 │
 ├── repository # Camada de repositório, responsável por acessar banco de dados e realizar operações de CRUD (Create, Read, Update, Delete) via JPA/Hibernate, além de consultas personalizadas
 │     ├── AccountRepository.kt # Repositório principal de conta, estendendo JpaRepository para operações básicas de CRUD
 │     ├── AccountQueryRepository.kt # Repositório de consultas personalizadas, contendo métodos para consultas/queries complexas ou específicas que não se encaixam no padrão do JpaRepository
 │     └── AccountCustomRepository.kt # Repositório customizado, contendo implementações personalizadas de métodos de acesso a dados que exigem lógica específica/personalizada ou otimizações
 │
 ├── service # Camada de serviço, responsável por implementar lógica de negócio da aplicação, orquestrando operações entre repositórios, validando regras de negócio e garantindo a integridade dos dados
 │     ├── AccountService.kt # Serviço principal de conta, contendo regras/métodos para criar, atualizar, excluir e obter contas, além de aplicar regras de negócio relacionadas a contas
 │     ├── CreateAccountService.kt # Serviço específico para criação de contas, contendo regras/lógica de negócio relacionada à criação, como validação de dados, verificação de duplicidade, atribuição de papéis padrão, etc
 │     ├── UpdateAccountService.kt # Serviço específico para atualização de contas, contendo regras/lógica de negócio relacionada à atualização, como validação de dados, controle de alterações, etc
 │     ├── DeleteAccountService.kt # Serviço específico para exclusão de contas, contendo regras/lógica de negócio relacionada à exclusão, como verificação de dependências, controle de status, etc
 │     ├── GetAccountService.kt # Serviço específico para obtenção de detalhes de conta individual, contendo regras/lógica de negócio relacionada à obtenção, como controle de acesso, formatação de dados, etc
 │     ├── ListAccountService.kt # Serviço específico para listagem de contas, contendo regras/lógica de negócio relacionada à listagem, como paginação, filtragem, ordenação, etc
 │     ├── AccountValidationService.kt # Serviço de validação de conta, contendo regras/lógica de negócio relacionada à validação de dados de conta, como validação de email, senha, formato de dados, etc
 │     └── AccountAuthService.kt # Serviço de autenticação e autorização de conta, contendo regras/lógica de negócio relacionada à autenticação (login, logout, refresh token) e controle de acesso (verificação de papéis/permissões)
 │
 └── utils # Camada de utilitários, contendo classes e métodos auxiliares para mapeamento de objetos (DTOs para entidades e vice-versa), validação de dados, constantes e outras funções utilitárias relacionadas ao domínio de conta
       ├── AccountMapper.kt # Mapeador para conversão entre entidades em DTOs, e vice-versa, de conta
       ├── AccountUtils.kt # Utilitários/funções diversas relacionados a conta, como formatação de dados, geração de senhas, etc
       ├── AccountValidator.kt # Validador para validações reutilizáveis de dados relacionados a conta, como validação de email, senha, formato de dados, etc
       ├── AccountConstants.kt # Constantes relacionadas a conta, como mensagens de erro, papéis padrão, etc
       └── AccountPermissions.kt # Definição/centralização de permissões e roles/papéis relacionados a conta, para controle de acesso

com.whateverer.feature.payment
 ├── controller
 │     ├── PaymentController.kt
 │     ├── RefundController.kt
 │     └── PaymentWebhookController.kt
 │
 ├── model
 │     ├── dto
 │     │     ├── CreatePaymentRequest.kt
 │     │     ├── PaymentResponse.kt
 │     │     ├── RefundRequest.kt
 │     │     ├── PaymentStatusResponse.kt
 │     │     └── InstallmentSimulationResponse.kt
 │     │
 │     └── entity
 │           ├── PaymentEntity.kt
 │           ├── RefundEntity.kt
 │           ├── PaymentMethodEntity.kt
 │           └── PaymentStatus.kt
 │
 ├── repository
 │     ├── PaymentRepository.kt
 │     ├── RefundRepository.kt
 │     └── PaymentQueryRepository.kt
 │
 ├── service
 │     ├── PaymentService.kt
 │     ├── RefundService.kt
 │     ├── PaymentGatewayService.kt
 │     ├── PaymentValidationService.kt
 │     ├── InstallmentService.kt
 │     └── PaymentWebhookService.kt
 │
 └── utils
       ├── PaymentMapper.kt
       ├── PaymentUtils.kt
       ├── PaymentValidator.kt
       ├── PaymentConstants.kt
       └── InstallmentCalculator.kt

src.test.kotlin.com.whateverer # Pacote de testes, organizado por tipo de teste (integração, unitário, arquitetura, e2e) e por domínio/feature (account, payment, order)
├── integration # Testes de integração, que verificam interação entre diferentes módulos ou camadas do sistema
│   ├── AccountIntegrationTest.kt # Teste de integração para funcionalidades relacionadas a conta, verificando interação entre camadas (controller, service, repository) e comportamento geral da funcionalidade de conta
│   ├── PaymentIntegrationTest.kt # Teste de integração para funcionalidades relacionadas a pagamento, verificando interação entre camadas (controller, service, repository) e comportamento geral da funcionalidade de pagamento
│   └── OrderIntegrationTest.kt # Teste de integração para funcionalidades relacionadas a pedido, verificando interação entre camadas (controller, service, repository) e comportamento geral da funcionalidade de pedido
├── unit # Testes unitários, que verificam comportamento de unidades isoladas de código, como métodos ou classes específicas, usando mocks para dependências externas
│   ├── account # Testes unitários para funcionalidades relacionadas a conta, organizados por camada (controller, service, repository)
│   │   ├── controller # Testes unitários para camada de controle de conta, verificando comportamento dos endpoints REST, validação de dados de entrada e respostas adequadas
│   │   │   └── AccountControllerTest.kt # Teste unitário para AccountController, verificando comportamento dos endpoints de conta
│   │   ├── service # Testes unitários para camada de serviço de conta, verificando lógica de negócio, regras de validação e interação com repositórios
│   │   │   ├── AccountServiceTest.kt # Teste unitário para AccountService, verificando regras de negócio relacionadas a conta
│   │   │   └── AccountValidationServiceTest.kt # Teste unitário para AccountValidationService, verificando regras de validação de dados relacionados a conta
│   │   └── repository # Testes unitários para camada de repositório de conta, verificando operações de acesso a dados e consultas personalizadas
│   │       ├── AccountRepositoryTest.kt # Teste unitário para AccountRepository, verificando operações básicas de CRUD e consultas simples
│   │       └── AccountQueryRepositoryTest.kt # Teste unitário para AccountQueryRepository, verificando consultas personalizadas e complexas relacionadas a conta
│   ├── payment
│   └── order
├── architecture # Testes de arquitetura, que verificam conformidade do código com regras de arquitetura definidas, como modularização, dependências entre camadas, regras hexagonais e convenções de DDD
│   ├── ModularizationTest.kt # Teste de arquitetura para verificar modularização do código, garantindo que funcionalidades estejam organizadas em módulos coesos e com baixo acoplamento
│   ├── LayerDependencyTest.kt # Teste de arquitetura para verificar dependências entre camadas, garantindo que camadas superiores (controller) dependam apenas das camadas inferiores (service, repository) e não o contrário
│   ├── HexagonalRulesTest.kt # Teste de arquitetura para verificar regras hexagonais, garantindo que camada de domínio não dependa de detalhes de infraestrutura e que portas e adaptadores estejam corretamente implementados
│   └── DddConventionsTest.kt # Teste de arquitetura para verificar convenções de DDD (Domain-Driven Design), garantindo que entidades, agregados, repositórios e serviços estejam organizados de acordo com práticas recomendadas de DDD
└── e2e # Testes end-to-end, que verificam comportamento do sistema como todo, simulando cenários reais de uso e verificando integração entre todas camadas e módulos
    ├── CustomerFlowE2ETest.kt # Teste end-to-end para fluxo de cliente, simulando cenários reais de uso relacionados a clientes, como criação, atualização, obtenção e exclusão de clientes, verificando integração entre todas as camadas e módulos relacionados a cliente
    └── OrderFlowE2ETest.kt # Teste end-to-end para fluxo de pedido, simulando cenários reais de uso relacionados a pedidos, como criação, atualização, obtenção e exclusão de pedidos, verificando integração entre todas camadas e módulos relacionados a pedido

Elaborado por Mateus Schwede
ubsocial.github.io