DDD. Event sourcing. CQRS. REST. Modular. Microservices. Kotlin. Spring. Axon platform. Apache Kafka. RabbitMQ
This is a thin layer which coordinates the application activity. It does not contain business logic. It does not hold the state of the business objects
We designed and structured our loosely coupled components in a modular way, and that enable us to choose different deployment strategy and take first step towards Microservices architectural style.
Each microservice:
RabbitMQ is the most popular open source message broker. It is used to route and distribute events
.
It supports several messaging protocols, directly and through the use of plugins:
This messaging pattern supports delivering a message to multiple consumers.
We configured our (micro)services to use publish-subscribe model, by setting unique queue for each (micro)service.
This queues are bind to one common exchange (events.fanout.exchange
).
RabbitMQ allows more sophisticated message routing then Apache Kafka can offer. Having one exchange bind to every service queue covered our scenario, but you can do more if you like.
The Spring Cloud connector setup uses the service registration and discovery mechanism described by Spring Cloud for distributing the command bus (commands
).
You are thus left free to choose which Spring Cloud implementation to use to distribute your commands.
An example implementation is the Eureka Discovery/Eureka Server combination.
curl http://localhost:8084/restaurants
curl -i -X POST --header 'Content-Type: application/json' --header 'Accept: */*' -d '{
"menuItems": [
{
"id": "id1",
"name": "name1",
"price": 100
}
],
"name": "Fancy"
}' 'http://localhost:8084/restaurants'
curl -i -X PUT --header 'Content-Type: application/json' --header 'Accept: */*' 'http://localhost:8084/restaurants/RESTAURANT_ID/orders/RESTAURANT_ORDER_ID/markprepared'
curl http://localhost:8082/customers
curl -i -X POST --header 'Content-Type: application/json' --header 'Accept: */*' -d '{
"firstName": "Ivan",
"lastName": "Dugalic",
"orderLimit": 1000
}' 'http://localhost:8082/customers'
curl http://localhost:8081/couriers
curl -i -X POST --header 'Content-Type: application/json' --header 'Accept: */*' -d '{
"firstName": "John",
"lastName": "Doe",
"maxNumberOfActiveOrders": 20
}' 'http://localhost:8081/couriers'
curl -i -X PUT --header 'Content-Type: application/json' --header 'Accept: */*' 'http://localhost:8081/couriers/COURIER_ID/orders/COURIER_ORDER_ID/assign'
curl -i -X PUT --header 'Content-Type: application/json' --header 'Accept: */*' 'http://localhost:8081/couriers/COURIER_ID/orders/COURIER_ORDER_ID/markdelivered'
curl http://localhost:8083/orders
curl -i -X POST --header 'Content-Type: application/json' --header 'Accept: */*' -d '{
"customerId": "CUSTOMER_ID",
"orderItems": [
{
"id": "id1",
"name": "name1",
"price": 100,
"quantity": 0
}
],
"restaurantId": "RESTAURANT_ID"
}' 'http://localhost:8083/orders'
Note: Replace CUSTOMER_ID and RESTAURANT_ID with concrete values.
This project is driven using Maven.
$ git clone https://github.com/idugalic/digital-restaurant
$ cd digital-restaurant
$ mvn clean install
NOTE: Docker is required. We use it to start RabbitMQ
$ docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management
$ cd digital-restaurant/drestaurant-apps/drestaurant-microservices-rest/drestaurant-microservices-rest-courier
$ mvn spring-boot:run
$ cd digital-restaurant/drestaurant-apps/drestaurant-microservices-rest/drestaurant-microservices-rest-discovery-server
$ mvn spring-boot:run
$ cd digital-restaurant/drestaurant-apps/drestaurant-microservices-rest/drestaurant-microservices-rest-customer
$ mvn spring-boot:run
$ cd digital-restaurant/drestaurant-apps/drestaurant-microservices-rest/drestaurant-microservices-rest-restaurant
$ mvn spring-boot:run
$ cd digital-restaurant/drestaurant-apps/drestaurant-microservices-rest/drestaurant-microservices-rest-order
$ mvn spring-boot:run