Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Creditas/kotlin-ddd-sample
A sample DDD/CQRS project using KOTLIN :beer:
https://github.com/Creditas/kotlin-ddd-sample
axonframework cqrs ddd kotlin
Last synced: 3 months ago
JSON representation
A sample DDD/CQRS project using KOTLIN :beer:
- Host: GitHub
- URL: https://github.com/Creditas/kotlin-ddd-sample
- Owner: Creditas
- Archived: true
- Created: 2018-05-14T03:31:29.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2020-08-06T17:19:47.000Z (over 4 years ago)
- Last Synced: 2024-07-23T15:32:38.828Z (4 months ago)
- Topics: axonframework, cqrs, ddd, kotlin
- Language: Kotlin
- Homepage:
- Size: 331 KB
- Stars: 285
- Watchers: 158
- Forks: 50
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Kotlin DDD Sample
**Kotlin DDD Sample** is a open-source project meant to be used as a start point, or an inspiration, for those who want to build Domain Driven Design applications in Kotlin. The domain model was inspired by [this](https://github.com/mcapanema/ddd-rails-example) repo where we built a sample project using Rails.
**NOTE:** This is NOT intended to be a definitive solution or a production ready project
# Technologies/frameworks/tools involved
- Spring
- Axon Framework
- CommandGateway (Command Handlers)
- EventBus (Event Handlers)
- Gradle# Architecture overview
## Layers
- **Web**: Spring controllers and actions
- **Application**: Orchestrates the jobs in the domain needed to be done to accomplish a certain "use case"
- **Domain**: Where the business rules resides
- **Infrastructure**: Technologies concerns resides here (database access, sending emails, calling external APIs)## CQRS
CQRS splits your application (and even the database in some cases) into two different paths: **Commands** and **Queries**.
### Command sideEvery operation that can trigger an side effect on the server must pass through the CQRS "command side". I like to put the `Handlers` (commands handlers and events handlers) inside the application layer because their goals are almost the same: orchestrate domain operations (also usually using infrastructure services).
![command side](docs/images/command_side_with_events.jpg)### Query side
Pretty straight forward, the controller receives the request, calls the related query repo and returns a DTO (defined on infrastructure layer itself).
![query side](docs/images/query_side.jpg)
# The domain (problem space)
This project is based on a didactic domain that basically consists in maintaining an Order (adding and removing items in it). The operations supported by the application are:
* Create an order
* Add products ta a given order
* Change product quantity
* Remove product
* Pay the order (this operation fires an Event for the shipping bounded context)
* Shipping (side effect of the above event): ships product and notify userPretty simple, right?
# Setup
**Linux/MacOS:**
```
./gradlew build
```**Windows:**
```
gradlew.bat build
```### RabbitMQ setup
There is a file named `AMQPRabbitConfiguration` in this repo (located [here](https://github.com/fabriciorissetto/kotlin-ddd-sample/blob/master/web/src/main/configuration/injection/AMQPRabbitConfiguration.kt)) where the configuration needed by axon to integrate with RabbitMQ (to send end receive persistent messages) is stored. To use that, just remove the comments.
You need a running rabbit, you can start one in a docker container using the following commands:
```bash
docker pull rabbitmq
docker run -d --hostname my-rabbit --name some-rabbit rabbitmq:3-management
```You can access the rabbit UI by this url: [http://172.17.0.2:15672](http://172.17.0.2:15672).
* **User**: guest
* **Password**: guest
That's it. You don't need to do anything else, the setup in the `AMQPRabbitConfiguration` class will create the necessary queue and exchange in Rabbit and also configure axon accordingly. Note that if you customize something in your rabbit server you need to adjust the `application.properties` file (here we are using the default ports, ips, etc).This both dependencies are used just for Rabbit:
* `org.springframework.boot:spring-boot-starter-amqp`: enables AMQP in Spring Boot
* `org.axonframework:axon-amqp`: configures some beans for axon to integrate with `SpringAMQPMessageSource` class from the above dependencyIf you don't want o use an AMQP you can remove this dependencies from the web project gradle's file.
# Tests
```
./gradlew test
```### Postman requests
You can trigger all the operations of this project using the requests inside [this json](https://github.com/fabriciorissetto/kotlin-ddd-sample/blob/master/docs/postman_example_requests.json) (just import it on your local postman).
# Backlog
- [x] Implement Unit Tests examples (Domain layer)
- [ ] Implement Integrated Tests examples (Web layer)
- [ ] Include docker container with JDK and gradle configured
- [ ] Configure Swagger and Swagger UI
- [ ] Include a Event Sourced bounded context or Aggregate
- [ ] Domain Notifications instead of raising exceptions
- [ ] Implement concrete repositories with JPA (the current implementations just returns fake instances)
- [ ] Configure JPMS (java 9 modules)Contributions are welcome! :heartbeat: