Skip to content
My Guidelines
Guides
In this guide (8 items)

Architecture Overview

Architecture Overview

Project-agnostic catalog. Part of the Diagram Catalog. Covers: high-level architectural pattern, hexagonal implementation, module structure.

Replace com.example.platform / platform-service placeholders with your project’s actual package and service name when applying patterns.


1. Architecture Overview

1.1 Main Architectural Pattern

The project implements Hexagonal Architecture (Ports & Adapters) combined with Clean Architecture, structured in clearly defined layers:

┌─────────────────────────────────────────────────────────────┐
│ Entry Points (Inbound Adapters — Infrastructure) │
│ REST, GraphQL, Schedulers, Webhooks, Kafka Consumers │
└──────────────────┬──────────────────────────────────────────┘
│ (Inbound Ports)
┌─────────────────▼────────────────────────────────────────┐
│ Application Layer │
│ • Use Cases (Business Logic) │
│ • Inbound Ports (Command/Query Interfaces) │
│ • Outbound Ports (Repository/Publisher Interfaces) │
│ • Commands (Input DTOs) │
└──────────────┬─────────────────┬──────────────────────────┘
│ │ (Outbound Ports)
┌──────────────▼─┐ ┌────────────▼────────────────────┐
│ Domain Layer │ │ Driven Adapters │
│ • Entities │ │ • JDBC Repositories │
│ • Value Objs │ │ • Kafka Publishers │
│ • Exceptions │ │ • Redis Cache │
│ • Utils │ │ • Metrics Publishers │
└────────────────┘ └─────────────────────────────────┘

1.2 Core Principles

  • Dependency Inversion: All dependencies point inward (toward Domain)
  • Port-Based Design: All external communication through ports
  • Framework Independence: Domain and Application layers are pure Kotlin
  • Testability: Ports enable easy mocking and unit testing
  • Single Responsibility: Each layer has a clear, distinct purpose

2. Hexagonal Architecture Implementation

2.1 Layers Description

Domain Layer (Core/Center)

  • Location: domain/
  • Purpose: Contains business entities and domain logic
  • Dependencies: None (completely independent)
  • Contains:
    • Organization, User (Entities)
    • OrganizationStatus, Roles (Enums)
    • OrganizationNotFoundException (Domain Exceptions)
    • MdcUtil, TraceContextUtil (Domain Utilities)

Application Layer (Use Cases)

  • Location: application/
  • Purpose: Orchestrates business workflows
  • Dependencies: Domain only
  • Contains:
    • Inbound Ports: Define how external world invokes the app
    • Outbound Ports: Define how app communicates with infrastructure
    • Use Cases: Implement business logic using domain entities
    • Commands: Input DTOs for use cases

Infrastructure Layer (Adapters)

  • Location: infrastructure/
  • Purpose: Implements technical details
  • Dependencies: Application, Domain, External libraries
  • Contains:
    • Entry Points:
      • rest-controller: REST API endpoints.
      • graphql-controllers: GraphQL schema and resolvers.
      • webhooks-controller: External webhook handlers.
      • scheduler-task: Periodic background tasks.
      • kafka-consumer: Message queue consumers.
    • Driven Adapters: JDBC, Kafka, Redis, Metrics

Bootstrap Layer (Configuration)

  • Location: bootstrap/
  • Purpose: Dependency injection and app configuration
  • Dependencies: All other layers
  • Contains:
    • Spring Boot configuration
    • Bean definitions
    • Application properties

2.2 Complete Layer Diagram

┌─────────────────────────────────────────────────────────────────┐
│ BOOTSTRAP LAYER │
│ • Spring Boot Configuration (UseCaseConfig, ScheduleConfig) │
│ • Dependency Injection (Connects Ports ↔ Adapters) │
│ • Application Properties (application.yml) │
└────────────────────────┬────────────────────────────────────────┘
│ wires dependencies
┌────────────────┴────────────────┐
│ │
┌───────▼────────────────────┐ ┌────────▼──────────────────────┐
│ ENTRY POINTS │ │ DRIVEN ADAPTERS │
│ (Infrastructure) │ │ (Infrastructure) │
│ │ │ │
│ • REST Controllers │ │ • JDBC Repositories │
│ - OrganizationController │ │ - OrganizationRepoAdapter │
│ │ │ - UserRepositoryAdapter │
│ • Schedulers │ │ - OutboxRepositoryAdapter │
│ - OutboxTaskScheduler │ │ - JdbcTransaction<R> │
│ │ │ │
│ • Filters │ │ • Kafka Publishers │
│ - TraceIdFilter │ │ - OrganizationKafkaAdapter │
│ │ │ - UserKafkaAdapter │
└────────────┬───────────────┘ │ - OutboxKafkaAdapter │
│ implements │ │
│ inbound ports │ • Redis Cache │
│ │ - OrganizationCacheAdapter │
┌────────────▼────────────────────▼───────────────────────────────┐
│ APPLICATION LAYER │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ INBOUND PORTS │ │
│ │ • CreateOrganizationPort │ │
│ │ • GetOrganizationByIdPort │ │
│ │ • ChangeOrganizationStatusPort │ │
│ │ • SendOutboxMessagesPort (SDK) │ │
│ └────────────┬─────────────────────────────────────────────┘ │
│ │ implemented by │
│ ┌────────────▼─────────────────────────────────────────────┐ │
│ │ USE CASES │ │
│ │ • CreateOrganizationUseCase │ │
│ │ • GetOrganizationByIdUseCase │ │
│ │ • ChangeOrganizationStatusUseCase │ │
│ │ • SendOutboxMessagesUseCase (SDK) │ │
│ └────────────┬─────────────────────────────────────────────┘ │
│ │ depends on │
│ ┌────────────▼─────────────────────────────────────────────┐ │
│ │ OUTBOUND PORTS │ │
│ │ Repositories: │ │
│ │ • OrganizationRepositoryPort │ │
│ │ • UserRepositoryPort │ │
│ │ • OutboxRepositoryPort (SDK) │ │
│ │ │ │
│ │ Messaging: │ │
│ │ • MessagePublisherPort (SDK — consumed ONLY by the │ │
│ │ SDK dispatcher, NEVER by application use cases) │ │
│ │ │ │
│ │ Domain factories (no annotations): │ │
│ │ • EventMessageFactory (SDK) │ │
│ │ • OutboxEventFactory (SDK) │ │
│ │ │ │
│ │ Support: │ │
│ │ • TransactionPort<R> │ │
│ │ • ChainablePort<T> │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ COMMANDS │ │
│ │ • CreateOrganizationCommand │ │
│ │ • CommandMappers (to Domain) │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────┬─────────────────────────────────────┘
│ uses
┌────────────────────────▼─────────────────────────────────────┐
│ DOMAIN LAYER │
│ │
│ • Entities: Organization, User │
│ • Value Objects: (future implementation) │
│ • Enums: OrganizationStatus, Roles │
│ • Exceptions: OrganizationNotFoundException │
│ • Utils: MdcUtil, TraceContextUtil │
│ │
│ ⚠️ NO DEPENDENCIES - Pure Kotlin │
└───────────────────────────────────────────────────────────────┘

3. Module Structure

3.1 Directory Tree

platform-service/
│
├── domain/ # Core business logic
│ └── src/main/kotlin/.../domain/
│ ├── Organization.kt
│ ├── User.kt
│ ├── enums/
│ │ ├── OrganizationStatus.kt
│ │ └── Roles.kt
│ ├── exception/
│ │ └── OrganizationNotFoundException.kt
│ ├── support/
│ │ └── OutboxMessage.kt
│ └── util/
│ ├── MdcUtil.kt
│ └── TraceContextUtil.kt
│
├── application/ # Use cases and ports
│ └── src/main/kotlin/.../
│ ├── port/
│ │ ├── inbound/ # Entry contracts (service-owned)
│ │ │ ├── CreateOrganizationPort.kt
│ │ │ ├── GetOrganizationByIdPort.kt
│ │ │ └── ChangeOrganizationStatusPort.kt
│ │ │ # SendOutboxMessagesPort lives in codehuntersio-sdk-event-messaging
│ │ │
│ │ └── outbound/ # Exit contracts (service-owned)
│ │ └── repository/
│ │ ├── OrganizationRepositoryPort.kt
│ │ ├── UserRepositoryPort.kt
│ │ └── support/
│ │ ├── TransactionPort.kt
│ │ ├── TransactionCallbackPort.kt
│ │ └── ChainablePort.kt
│ │ # NO publisher/ folder.
│ │ # OutboxRepositoryPort + MessagePublisherPort + OutboxEventFactory
│ │ # come from codehuntersio-sdk-event-messaging — inject directly in use cases.
│ │
│ └── usecase/ # Business logic
│ └── organization/
│ ├── CreateOrganizationUseCase.kt
│ ├── GetOrganizationByIdUseCase.kt
│ ├── ChangeOrganizationStatusUseCase.kt
│ └── command/
│ ├── CreateOrganizationCommand.kt
│ └── mapper/
│ └── CommandMapper.kt
│
├── infrastructure/ # Technical implementations
│ ├── entry-points/ # Inbound adapters
│ │ ├── rest-controller/
│ │ │ └── .../controller/organization/
│ │ │ ├── OrganizationController.kt
│ │ │ └── model/
│ │ │ ├── request/
│ │ │ │ └── CreateOrganizationRequest.kt
│ │ │ └── response/
│ │ │ ├── CreatedOrganizationResponse.kt
│ │ │ └── OrganizationResponse.kt
│ │ │
│ │ └── scheduler-task/
│ │ └── OutboxTaskScheduler.kt
│ │
│ └── driven-adapters/ # Outbound adapters
│ ├── jdbc-repository/
│ │ └── OrganizationRepositoryAdapter.kt
│ ├── kafka-producer/
│ │ └── OrganizationKafkaPublisherAdapter.kt
│ ├── redis-cache/
│ │ └── OrganizationCacheAdapter.kt
│ └── metrics-publisher/
│ └── OrganizationMetricsAdapter.kt
│
└── bootstrap/ # Configuration
└── src/main/kotlin/.../config/
├── UseCaseConfig.kt
├── ScheduleConfig.kt
└── resources/
└── application.yml