The goal of this project is to play with Spring WebFlux
both on client and server side. For it, we will implement Spring Boot
Java Web applications (product-api
, customer-api
, order-api
, notification-api
and client-shell
) and use different databases like Cassandra
, MongoDB
, Postgres
and MySQL
.
On ivangfr.github.io, I have compiled my Proof-of-Concepts (PoCs) and articles. You can easily search for the technology you are interested in by using the filter. Who knows, perhaps I have already implemented a PoC or written an article about what you are looking for.
-
Spring Boot
Java Web application that exposes a REST API to manageproducts
. It usesMongoDB
as storage. -
Spring Boot
Java Web application that exposes a REST API to managecustomers
. It usesPostgres
as storage. -
Spring Boot
Web Java application that exposes a REST API to manageorders
. It usesCassandra
as storage. In order to get more information about anorder
, i.e, thename
of the customer who placed it or thename
orprice
of the products in the order,order-api
usesWebClient
andCompletableFuture
to fetch this information fromcustomer-api
andproduct-api
. -
Spring Boot
Web Java application that exposes a REST API to managenotifications
. -
Spring Boot
Shell Java application that has a couple of commands to interact withproduct-api
,customer-api
,order-api
andnotification-api
. The picture below show those commands.
-
Open a terminal and inside
spring-webflux-reactive-databases
root folder run./init-environment.sh
-
Wait for the script to finish
-
product-api
Open a new terminal and, inside
spring-webflux-reactive-databases
root folder, run the following command./mvnw clean spring-boot:run --projects product-api
-
customer-api
Open a new terminal and, inside
spring-webflux-reactive-databases
root folder, run the following command./mvnw clean spring-boot:run --projects customer-api
-
order-api
Open a new terminal and, inside
spring-webflux-reactive-databases
root folder, run the following command./mvnw clean spring-boot:run --projects order-api
-
notification-api
Open a new terminal and, inside
spring-webflux-reactive-databases
root folder, run the following command./mvnw clean spring-boot:run --projects notification-api
-
client-shell
Open a new terminal and, inside
spring-webflux-reactive-databases
root folder, run the following command to build the executable jar file./mvnw clean package --projects client-shell -DskipTests
To start
client-shell
run./client-shell/target/client-shell-1.0.0.jar
-
- In a terminal, make sure you are in
spring-webflux-reactive-databases
root folder - Run the following script to build the Docker images
- JVM
./docker-build.sh
- Native (it's not implemented yet)
./docker-build.sh native
- JVM
- In a terminal, make sure you are in
-
-
product-api
Environment Variable Description MONGODB_HOST
Specify host of the Mongo
database to use (defaultlocalhost
)MONGODB_PORT
Specify port of the Mongo
database to use (default27017
) -
customer-api
Environment Variable Description POSTGRES_HOST
Specify host of the Postgres
database to use (defaultlocalhost
)POSTGRES_PORT
Specify port of the Postgres
database to use (default5432
) -
order-api
Environment Variable Description CASSANDRA_HOST
Specify host of the Cassandra
database to use (defaultlocalhost
)CASSANDRA_PORT
Specify port of the Cassandra
database to use (default9042
)PRODUCT_API_HOST
Specify host of the product-api
to use (defaultlocalhost
)PRODUCT_API_PORT
Specify port of the product-api
to use (default9080
)CUSTOMER_API_HOST
Specify host of the customer-api
to use (defaultlocalhost
)CUSTOMER_API_PORT
Specify port of the customer-api
to use (default9081
) -
notification-api
Environment Variable Description MYSQL_HOST
Specify host of the MySQL
database to use (defaultlocalhost
)MYSQL_PORT
Specify port of the MySQL
database to use (default3306
)CUSTOMER_API_HOST
Specify host of the customer-api
to use (defaultlocalhost
)CUSTOMER_API_PORT
Specify port of the customer-api
to use (default9081
)ORDER_API_HOST
Specify host of the order-api
to use (defaultlocalhost
)ORDER_API_PORT
Specify port of the order-api
to use (default9082
) -
client-shell
Environment Variable Description PRODUCT_API_HOST
Specify host of the product-api
to use (defaultlocalhost
)PRODUCT_API_PORT
Specify port of the product-api
to use (default9080
)CUSTOMER_API_HOST
Specify host of the customer-api
to use (defaultlocalhost
)CUSTOMER_API_PORT
Specify port of the customer-api
to use (default9081
)ORDER_API_HOST
Specify host of the order-api
to use (defaultlocalhost
)ORDER_API_PORT
Specify port of the order-api
to use (default9082
)NOTIFICATION_API_HOST
Specify host of the notification-api
to use (defaultlocalhost
)NOTIFICATION_API_PORT
Specify port of the notification-api
to use (default9083
)
-
-
- In a terminal, make sure you are inside
spring-webflux-reactive-databases
root folder - Run following command
./start-apis.sh && ./start-shell.sh
- In a terminal, make sure you are inside
Application | URL |
---|---|
product-api | http://localhost:9080/swagger-ui.html |
customer-api | http://localhost:9081/swagger-ui.html |
order-api | http://localhost:9082/swagger-ui.html |
notification-api | http://localhost:9083/swagger-ui.html |
Warning: the ids shown below will be different when you run it
-
In
client-shell
terminal, import some products and customers by running the following command- If you are running using
Maven
script ../src/main/resources/samples.txt
- If you are running as Docker container
script /app/resources/samples.txt
- If you are running using
-
Get all customer
get-customers
It should return
{"id":"1","name":"Customer A","email":"customer.a@test.com","city":"Berlin","street":"NYC Strasse","number":"123"} {"id":"2","name":"Customer B","email":"customer.b@test.com","city":"Berlin","street":"LA Strasse","number":"234"} {"id":"3","name":"Customer C","email":"customer.c@test.com","city":"Berlin","street":"DC Strasse","number":"345"} ...
-
Get all products
get-products
It should return
{"id":"5ee3ee31b460d868af49f389","name":"product-1","price":199.99} {"id":"5ee3ee32b460d868af49f38a","name":"product-2","price":299.99} ...
-
Create an order where
Customer A
buys1 unit
ofproduct-1
and2 units
ofproduct-2
create-order --customerId 1 --products 5ee3ee31b460d868af49f389:1;5ee3ee32b460d868af49f38a:2
It should return
{ "orderId":"5aaad64c-4e80-48e0-926d-8f1b7027955a", "status":"OPEN", "created":"2020-06-12T22:09:59.558232", "products": [ {"id":"5ee3ee31b460d868af49f389", "quantity":1}, {"id":"5ee3ee32b460d868af49f38a", "quantity":2} ], "customerId":"1" }
-
Get details about the order created
get-order-detailed 5aaad64c-4e80-48e0-926d-8f1b7027955a
It should return
{ "orderId":"5aaad64c-4e80-48e0-926d-8f1b7027955a", "status":"OPEN", "created":"2020-06-12T22:09:59.558", "products": [ {"id":"5ee3ee32b460d868af49f38a", "name":"product-2", "quantity":2, "price":299.99}, {"id":"5ee3ee31b460d868af49f389", "name":"product-1", "quantity":1, "price":199.99} ], "customer": { "id":"1", "name":"Customer A", "email":"customer.a@test.com", "city":"Berlin", "street":"NYC Strasse", "number":"123" } }
-
To create a notification to the order created above
create-notification 5aaad64c-4e80-48e0-926d-8f1b7027955a
-
To check how fast
order-api
get details about the customer and products of an order, create another order whereCustomer A
order50
random productscreate-order-random --customerId 1 --numProducts 50
It should return
{ "orderId":"87133d36-67f0-4388-b15b-7d66ad739374", "status":"OPEN", "created":"2020-06-12T22:14:08.342338", "products": [ {"id":"5ee3ee32b460d868af49f38a", "quantity":4}, ... {"id":"5ee3ee32b460d868af49f396", "quantity":3} ], "customerId":"1" }
-
In another terminal, to get the details of the order previously created and the response time of this call, we are using
order-api
's endpointGET /api/orders/{orderId}/detailed
curl -w "\n\nResponse Time: %{time_total}s" -s localhost:9082/api/orders/87133d36-67f0-4388-b15b-7d66ad739374/detailed
It will return something like
{ "orderId":"87133d36-67f0-4388-b15b-7d66ad739374", "status":"OPEN", "created":"2020-06-12T22:14:08.342338", "products": [ {"id":"5ee3ee32b460d868af49f395", "name":"product-13", "quantity":4, "price":1399.99}, ... ], "customer": { "id":"1", "name":"Customer A", "email":"customer.a@test.com", "city":"Berlin", "street":"NYC Strasse", "number":"123" } } Response Time: 0.292698s
-
Cassandra
docker exec -it cassandra cqlsh USE mycompany; SELECT * FROM orders;
Type
exit
to get out ofcqlsh
-
MongoDB
docker exec -it mongodb mongosh productdb db.products.find()
Type
exit
to get out ofMongoDB shell
-
Postgres
docker exec -it postgres psql -U postgres -d customerdb \dt customer SELECT * FROM CUSTOMER;
Type
exit
to get out ofpsql
-
MySQL
docker exec -it -e MYSQL_PWD=secret mysql mysql -uroot --database notificationdb SELECT * FROM notification;
Type
exit
to get out ofMySQL monitor
- To stop
client-shell
, go to the terminal where it is running and typeexit
- To stop
product-api
,customer-api
andorder-api
- If you start them with
Maven
, go to the terminals were they are running and pressCtrl+C
- If you start them as Docker containers, go to a terminal and, inside
spring-webflux-reactive-databases
root folder, run the following script./stop-apis.sh
- If you start them with
- To stop and remove the database containers, network and volumes, go to a terminal and, inside
spring-webflux-reactive-databases
root folder, run the script below./shutdown-environment.sh
To remove all Docker images created by this project, go to a terminal and, inside spring-webflux-reactive-databases
root folder, run the following script
./remove-docker-images.sh