Clean, Object-oriented, Layered, Adaptable Application Architecture
English | 简体中文
This project is built using the COLA architecture. COLA is a clean, object-oriented, layered, and adaptable application architecture that helps reduce system entropy in complex application scenarios and improves development and operational efficiency. Whether it's traditional layered architecture, hexagonal architecture, or onion architecture, they all advocate for business-centric design, decoupling external dependencies, and separating business complexity from technical complexity. COLA architecture integrates CQRS, DDD, SOLID and other design principles on this foundation, forming a practical and implementable application architecture. For more details, please check the WIKI.
📚 For detailed component integration guides, please refer to the documentation:
- English Documentation - Component integration guides in English
- 中文文档 - 中文组件集成指南
---
title: Alibaba COLA Application Architecture Component Diagram
---
flowchart TB
%% Driving Adapters - Top
subgraph ActiveAdapters[" "]
direction LR
RPC_CLIENT(["«Driving Adapter»<br/>RPC Client"])
JOB{{"Job Scheduler"}}
MQ_CONSUMER(["«Driving Adapter»<br/>MQ Consumer"])
APP_TERMINAL(["«Driving Adapter»<br/>APP Terminal"])
end
%% COLA Core Components
ADAPTER["«Adapter Layer»<br/>eden-demo-cola-adapter"]
START["«Bootstrap»<br/>eden-demo-cola-start"]
APP_LAYER["«Application Layer»<br/>eden-demo-cola-app"]
CLIENT["«API Layer»<br/>eden-demo-cola-client"]
DOMAIN["«Domain Layer»<br/>eden-demo-cola-domain"]
INFRA["«Infrastructure Layer»<br/>eden-demo-cola-infrastructure"]
%% Interface Nodes
rpc((rpc))
http((http))
%% Driven Adapters - Bottom
subgraph PassiveDrivers[" "]
direction LR
THIRD_PARTY(["«Driven Adapter»<br/>Third-party API"])
MYSQL[("«Driven Adapter»<br/>MySQL")]
REDIS[("«Driven Adapter»<br/>Redis")]
MQ_PRODUCER[("«Driven Adapter»<br/>MQ")]
ES[("«Driven Adapter»<br/>Elasticsearch")]
MONGO[("«Driven Adapter»<br/>MongoDB")]
end
%% Driving Adapter Connections
RPC_CLIENT -.->|Network Call| rpc
rpc ---|RPC Interface| ADAPTER
APP_TERMINAL -.->|Frontend Integration| http
http ---|REST Interface| ADAPTER
RPC_CLIENT -.->|Code Integration| CLIENT
JOB <-.->|Task Scheduling| ADAPTER
MQ_CONSUMER <-.->|Consume Messages| ADAPTER
%% Internal Component Connections
START --> ADAPTER
ADAPTER -->|Inbound Adaptation, Data Assembly| APP_LAYER
APP_LAYER -->|Implement Interface| CLIENT
APP_LAYER -->|CQRS Commands| DOMAIN
APP_LAYER -->|CQRS Queries| INFRA
INFRA -.->|Dependency Inversion| DOMAIN
%% Driven Adapter Connections
INFRA -.->|API Call| THIRD_PARTY
INFRA -.->|Read/Write Data| MYSQL
INFRA -.->|Read/Write Cache| REDIS
INFRA -.->|Produce Messages| MQ_PRODUCER
INFRA -.->|Read/Write Index| ES
INFRA -.->|Read/Write Data| MONGO
%% Style Definitions
style ADAPTER fill:#90EE90,stroke:#333,stroke-width:2px
style START fill:#90EE90,stroke:#333,stroke-width:2px
style APP_LAYER fill:#90EE90,stroke:#333,stroke-width:2px
style CLIENT fill:#F0E68C,stroke:#333,stroke-width:2px
style DOMAIN fill:#90EE90,stroke:#333,stroke-width:2px
style INFRA fill:#90EE90,stroke:#333,stroke-width:2px
style RPC_CLIENT fill:#87CEEB,stroke:#333,stroke-width:1px
style JOB fill:#87CEEB,stroke:#333,stroke-width:1px
style MQ_CONSUMER fill:#87CEEB,stroke:#333,stroke-width:1px
style APP_TERMINAL fill:#87CEEB,stroke:#333,stroke-width:1px
style THIRD_PARTY fill:#FFB6C1,stroke:#333,stroke-width:1px
style MYSQL fill:#FFB6C1,stroke:#333,stroke-width:1px
style REDIS fill:#FFB6C1,stroke:#333,stroke-width:1px
style MQ_PRODUCER fill:#FFB6C1,stroke:#333,stroke-width:1px
style ES fill:#FFB6C1,stroke:#333,stroke-width:1px
style MONGO fill:#FFB6C1,stroke:#333,stroke-width:1px
style rpc fill:#fff,stroke:#333
style http fill:#fff,stroke:#333
- eden-demo-cola-adapter: Adapter layer, the inbound adapter in Hexagonal Architecture.
- eden-demo-cola-app: Application layer, responsible for CQRS command processing, update commands call the domain layer, query operations bypass the domain layer and directly call the infrastructure layer.
- eden-demo-cola-client: API layer, provides interfaces externally as a jar package.
- eden-demo-cola-domain: Domain layer, core business implementation. Unlike traditional layered architecture, it provides anti-corruption layer interfaces and does not depend on infrastructure layer technical implementations.
- eden-demo-cola-infrastructure: Infrastructure layer, the outbound adapter in Hexagonal Architecture, encapsulates technical details, uses Dependency Inversion to implement the anti-corruption layer interfaces exposed by Domain.
- eden-demo-cola-start: Application bootstrap entry, unified management of application configuration and delivery.
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#90EE90',
'primaryTextColor': '#000',
'primaryBorderColor': '#333',
'lineColor': '#333',
'secondaryColor': '#87CEEB',
'tertiaryColor': '#FFB6C1',
'noteBkgColor': '#FFFACD',
'noteTextColor': '#333',
'noteBorderColor': '#DAA520',
'actorBkg': '#87CEEB',
'actorBorder': '#333',
'actorTextColor': '#000',
'signalColor': '#333',
'signalTextColor': '#333'
},
'sequence': {
'actorMargin': 50,
'boxMargin': 10,
'boxTextMargin': 5,
'noteMargin': 10,
'messageMargin': 35,
'mirrorActors': true,
'useMaxWidth': true
}
}}%%
sequenceDiagram
autonumber
box rgb(135,206,235,0.3) Driving Adapter
participant A as Driving Adapter
end
box rgb(144,238,144,0.3) COLA Application Architecture
participant B as eden-demo-cola-adapter
participant C as eden-demo-cola-app
participant D as eden-demo-cola-domain
participant E as eden-demo-cola-infrastructure
end
box rgb(255,182,193,0.3) Driven Adapter
participant F as Driven Adapter
end
box rgb(240,230,140,0.3) Extension Point
participant G as Extension Point
end
Note over A,G: Scenario 1: HTTP Data Update Request
A->>B: 1. Send write request
B->>C: 2. Adapter assembles DTO
C->>C: 3. CQRS parses command parameters
C->>G: 4. Call extension based on command (optional)
C->>D: 5. Call domain layer
D->>E: 6. Execute data write via anti-corruption layer
E->>F: 7. Call underlying component for write operation
F-->>E:
E-->>C: 8. Return result data
C-->>B: 9. Assemble return data
B-->>A: 10. Response
Note over A,G: Scenario 2: HTTP Data Query Request
A->>B: 11. Send read request
B->>C: 12. Adapter assembles DTO
C->>C: 13. CQRS parses query parameters
C->>E: 14. Execute data read operation
E->>F: 15. Call underlying component for read operation
F-->>E:
E-->>C: 16. Return query data
C-->>B: 17. Assemble return data
B-->>A: 18. Response
Note over A,G: Scenario 3: MQ Message Driven / Job Scheduled Task
A->>B: 19. Listen for event trigger
B->>C: 20. CQRS dispatch
alt Domain Call
C->>D: 21. Call domain layer
D->>E: 22. Execute data write via anti-corruption layer
E->>F: 23. Call underlying component for write operation
F-->>E:
E-->>C: 24. Return update result
else Simple Query
C->>E: 25. Execute data read operation
E->>F: 26. Call underlying component for read operation
F-->>E:
E-->>C: 27. Return query data
end
C->>C: 28. Internal processing (ACK/Status)
C-->>B: 29. Report processing result
B-->>A: 30. Report result
This project uses Maven for building. The quickest way to get started is to git clone to your local machine. To simplify unnecessary technical details, this project depends on eden-architect. Execute mvn install -T 4C in the project root directory to complete the build.
This project is configured with a dev environment by default. For your convenience, all external component dependencies are disabled.
- Run
mvn installin the project directory (add-DskipTestsparameter to skip tests). - Navigate to
eden-demo-cola-startdirectory, executemvn spring-boot:runor start theColaApplicationclass. If successful, you'll see the Spring Boot startup screen. - A simple
RestControllerinterface is implemented in this application. Click Demo API to test. - Since frontend-backend separation is the mainstream approach, please implement pages as needed. Accessing http://localhost:8081 will redirect to a 404 page.
Enable Service Registry and Configuration Management: We recommend using Nacos. You can refer to Nacos Quick Start for quick setup. Modify the configuration file according to your Nacos address: bootstrap-dev.yml:
spring:
cloud:
nacos:
discovery: # Service Registry
enabled: true # Disabled by default, enable as needed
config: # Configuration Center
enabled: true # Disabled by default, enable as neededModify Default Data Source: This project uses H2 in-memory database by default, with Liquibase automatically initializing SQL scripts at startup. If you're using an external MySQL database, adjust the connection information here: application-dev.yml, and remove any H2 related configurations.
spring:
# h2: # In-memory database
# console:
# enabled: true # Do not enable in production
# path: /h2-console
# settings:
# trace: false
# web-allow-others: false
datasource: # Data source management
username:
password:
url: jdbc:mysql://host:port/schema?rewriteBatchedStatements=true&useSSL=false&useOldAliasMetadataBehavior=true&useUnicode=true&serverTimezone=GMT%2B8
driver-class-name: com.mysql.cj.jdbc.DriverAdditionally, this project includes usage examples for common components like Redis cache, RocketMQ message queue, and ShardingSphere database sharding, all disabled by default via xxx.enabled. You can enable configurations as needed to complete component integration.
Execute mvn -T 4C clean package to package into a runnable fat jar, then start with the following command:
java -Dserver.port=8081 -jar target/eden-demo-cola-start.jarExecute mvn -P assembly -T 4C clean package to create compressed packages. Copy one of the following to your desired deployment directory:
- target/eden-demo-cola-start-assembly.zip
- target/eden-demo-cola-start-assembly.tar.gz
After extraction, you can find startup.sh or startup.bat scripts in the bin directory. Simply run them to start.
Google Jib plugin allows you to build images without installing Docker.
mvn -T 4C -U package
mvn -pl eden-demo-cola-start jib:build -Djib.disableUpdateChecks=true -DskipTestsBuild images based on Spring Boot's layered feature. Ensure Docker is properly installed, then execute:
docker build -f docker/Dockerfile -t eden-demo-cola:{tag} .For application-centric deployment, we recommend using Helm to manage K8s resource descriptors. Use the following commands for installation and uninstallation:
helm install eden-demo-cola ./helm # Deploy resources
helm uninstall eden-demo-cola # Uninstall resourcesCI/CD Tool Options: Jenkins, CODING, Codeup, Zadig, KubeVela
The following demonstrates continuous build and deployment using Jenkins.
The following demonstrates continuous build and deployment using CODING. Anchor Link
This project uses RBAC (Role-Based Access Control) as an example to demonstrate how to implement DDD in COLA architecture.
Strategic Design - Bounded Context Division
The RBAC system is divided into four bounded contexts: User, Role, Permission, and Menu. Each context contains aggregate roots, gateway interfaces, and domain services. The RBAC context serves as a coordinator responsible for cross-context business orchestration.
graph TB
subgraph User Context
User[User Aggregate Root]
UserGateway[User Gateway]
UserDomainService[User Domain Service]
end
subgraph Role Context
Role[Role Aggregate Root]
RoleGateway[Role Gateway]
end
subgraph Permission Context
Permission[Permission Aggregate Root]
PermissionGateway[Permission Gateway]
end
subgraph Menu Context
Menu[Menu Aggregate Root]
MenuGateway[Menu Gateway]
end
subgraph RBAC Context
RbacDomainService[RBAC Domain Service]
end
User -.->|Assign| Role
Role -.->|Associate| Permission
Role -.->|Associate| Menu
RbacDomainService --> User
RbacDomainService --> Role
RbacDomainService --> Permission
Domain Model
classDiagram
class User {
-Long id
-Login login
-Email email
-Password password
-UserStatus status
+create(login, email, password) User
+changeEmail(newEmail)
+changePassword(currentPassword, newPassword)
+activate()
+lock()
+unlock()
+disable()
+verifyPassword(plainPassword) boolean
+canLogin() boolean
}
class Role {
-Long id
-RoleCode code
-RoleName name
-String description
-RoleStatus status
-Integer sort
+create(code, name) Role
+updateInfo(name, description, sort)
+enable()
+disable()
+isEnabled() boolean
}
class Permission {
-Long id
-PermissionCode code
-String name
-PermissionType type
-Long parentId
-String description
-Integer sort
+create(code, name, type) Permission
+updateInfo(name, description, sort)
+setParent(parentId)
+isMenuPermission() boolean
+isButtonPermission() boolean
+isRoot() boolean
}
class Menu {
-Long id
-String name
-MenuPath path
-String icon
-Long parentId
-Integer sort
-MenuStatus status
-String component
+create(name, path, parentId) Menu
+updateInfo(name, icon, sort, component)
+updatePath(path)
+setParent(parentId)
+show()
+hide()
+isVisible() boolean
+isRootMenu() boolean
}
class Login {
<<Value Object>>
-String value
+of(value) Login
}
class Email {
<<Value Object>>
-String value
+of(value) Email
}
class Password {
<<Value Object>>
-String value
+of(plainPassword) Password
+matches(plainPassword) boolean
}
class RoleCode {
<<Value Object>>
-String value
+of(value) RoleCode
}
class RoleName {
<<Value Object>>
-String value
+of(value) RoleName
}
class PermissionCode {
<<Value Object>>
-String value
+of(value) PermissionCode
}
class MenuPath {
<<Value Object>>
-String value
+of(value) MenuPath
}
User *-- Login
User *-- Email
User *-- Password
Role *-- RoleCode
Role *-- RoleName
Permission *-- PermissionCode
Menu *-- MenuPath
User "1" -- "*" Role : Assign
Role "1" -- "*" Permission : Associate
Role "1" -- "*" Menu : Associate
Domain Events
sequenceDiagram
participant App as Application Layer
participant User as User Aggregate Root
participant EventPublisher as Event Publisher
participant EventHandler as Event Handler
App->>User: Create User
User->>User: Register UserCreatedEvent
App->>User: Get Domain Events
App->>EventPublisher: Publish Event
EventPublisher->>EventHandler: Handle UserCreatedEvent
EventHandler->>EventHandler: Send Welcome Email
App->>User: Clear Domain Events
COLA Layers and DDD Mapping
graph TB
subgraph Adapter Layer
Controller[REST Controller]
RpcProvider[RPC Provider]
end
subgraph Application Layer
Service[Application Service]
CmdExe[Command Executor]
QryExe[Query Executor]
Assembler[DTO Assembler]
end
subgraph Domain Layer
Entity[Aggregate Root/Entity]
ValueObject[Value Object]
DomainService[Domain Service]
DomainEvent[Domain Event]
Gateway[Anti-corruption Layer Interface]
end
subgraph Infrastructure Layer
GatewayImpl[Gateway Implementation]
Mapper[Data Mapper]
DataObject[Data Object]
EventHandler[Event Handler]
end
Controller --> Service
RpcProvider --> Service
Service --> CmdExe
Service --> QryExe
CmdExe --> Entity
CmdExe --> DomainService
CmdExe --> Gateway
QryExe --> Mapper
Entity --> ValueObject
Entity --> DomainEvent
DomainService --> Gateway
GatewayImpl -.->|Implements| Gateway
GatewayImpl --> Mapper
Mapper --> DataObject
EventHandler --> DomainEvent
CQRS Command Query Separation
flowchart LR
subgraph Input[" "]
A1[Controller]
A2[Controller]
end
subgraph Service[" "]
B1[CommandService]
B2[QueryService]
end
subgraph Executor[" "]
C1[CmdExe]
C2[QryExe]
end
subgraph Core[" "]
D1[Domain]
D2["-"]
end
subgraph Data[" "]
E1[Gateway]
E2[Mapper]
end
subgraph Storage[" "]
F1[(Database)]
F2[(Database)]
end
A1 -->|Command| B1 --> C1 --> D1 --> E1 --> F1
A2 -->|Query| B2 --> C2 -.->|Bypass Domain| E2 --> F2
style D1 fill:#90EE90,stroke:#333
style D2 fill:#f5f5f5,stroke:#ddd,stroke-dasharray: 5 5
style E1 fill:#90EE90,stroke:#333
style E2 fill:#FFB6C1,stroke:#333
| Type | Path | Characteristics |
|---|---|---|
| Command (Write) | Controller → Service → CmdExe → Domain → Gateway → DB | Goes through Domain layer, ensures business rules |
| Query (Read) | Controller → Service → QryExe → Mapper → DB | Bypasses Domain layer, improves performance |
eden-demo-cola-domain/
├── user/ # User Bounded Context
│ ├── entity/ # Entities
│ │ ├── User.java # User Aggregate Root
│ │ └── UserStatus.java # User Status Enum
│ ├── valueobject/ # Value Objects
│ │ ├── Login.java # Login Account
│ │ ├── Email.java # Email
│ │ └── Password.java # Password
│ ├── event/ # Domain Events
│ │ ├── UserCreatedEvent.java # User Created Event
│ │ └── UserEmailChangedEvent.java
│ ├── domainservice/ # Domain Services
│ │ └── UserDomainService.java
│ ├── gateway/ # Anti-corruption Layer Interfaces
│ │ └── UserGateway.java
│ └── statemachine/ # State Machine
│ └── UserStateMachine.java
├── role/ # Role Bounded Context
│ ├── entity/
│ │ ├── Role.java # Role Aggregate Root
│ │ └── RoleStatus.java
│ ├── valueobject/
│ │ ├── RoleCode.java
│ │ └── RoleName.java
│ └── gateway/
│ └── RoleGateway.java
├── permission/ # Permission Bounded Context
│ ├── entity/
│ │ ├── Permission.java # Permission Aggregate Root
│ │ └── PermissionType.java
│ ├── valueobject/
│ │ └── PermissionCode.java
│ └── gateway/
│ └── PermissionGateway.java
├── menu/ # Menu Bounded Context
│ ├── entity/
│ │ ├── Menu.java # Menu Aggregate Root
│ │ └── MenuStatus.java
│ ├── valueobject/
│ │ └── MenuPath.java
│ └── gateway/
│ └── MenuGateway.java
└── rbac/ # RBAC Cross-context Coordination
└── domainservice/
└── RbacDomainService.java
| Principle | Description | Example |
|---|---|---|
| Aggregate Root | Entry point of an aggregate, ensures consistency within the aggregate | User, Role, Permission, Menu |
| Value Object | No unique identifier, equality determined by attribute values | Login, Email, Password, RoleCode |
| Domain Event | Records important events that occur in the domain | UserCreatedEvent, UserEmailChangedEvent |
| Domain Service | Handles business logic across aggregates | UserDomainService, RbacDomainService |
| Anti-corruption Layer | Isolates domain layer from infrastructure layer | UserGateway, RoleGateway |
| Dependency Inversion | Domain layer defines interfaces, infrastructure layer implements | Gateway interface and GatewayImpl implementation |
In the era of agile development, GitFlow seems inadequate. We've developed a simple and easy-to-use workflow for the team. Anchor Link
For detailed branch management strategies, Maven version management, and agile iteration cycles, please refer to the Git Workflow.
Analyze the entire trace including HTTP request latency, RPC call details, Log business logs, SQL and Cache execution time through TraceId. Anchor Link
Configure flow control rules based on business load, and view interface QPS and rate limiting status at any time. Anchor Link
Use runtime probes for dynamic service discovery, out-of-the-box, allowing you to diagnose your application in low-load environments. Anchor Link
The project version number follows the x.y.z format, where x is a numeric value starting from 0 and not limited to the 0-9 range. During the incubation phase, the first digit is fixed at 0, i.e., version numbers follow the 0.x.x format.
- Incubation version: 0.0.1-SNAPSHOT
- Development version: 1.0.0-SNAPSHOT
- Release version: 1.0.0
Version iteration rules:
- 1.0.0 <> 1.0.1: Compatible
- 1.0.0 <> 1.1.0: Mostly compatible
- 1.0.0 <> 2.0.0: Incompatible
Due to significant architectural changes between Spring Boot 2.4.x and Spring Boot 3.0.x, we maintain branches aligned with Spring Boot versions:
- 2.4.x branch for
Spring Boot 2.4.x, minimum JDK 8. - 2.7.x branch for
Spring Boot 2.7.x, minimum JDK 11. - 3.5.x branch for
Spring Boot 3.5.x, minimum JDK 17. - 4.0.x branch for
Spring Boot 4.0.x, minimum JDK 17.
Please refer to CHANGELOG.md







