{"id":16627117,"url":"https://github.com/ttulka/ddd-example-ecommerce-microservices","last_synced_at":"2025-03-21T15:31:16.978Z","repository":{"id":95749907,"uuid":"309413330","full_name":"ttulka/ddd-example-ecommerce-microservices","owner":"ttulka","description":"Domain-driven design microservices example","archived":false,"fork":false,"pushed_at":"2023-12-11T15:11:31.000Z","size":609,"stargazers_count":61,"open_issues_count":0,"forks_count":22,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-18T02:36:10.461Z","etag":null,"topics":["architecture","ddd","docker","domain-driven-design","event-driven","example","kubernetes","microservices","oop","soa","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ttulka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-02T15:32:01.000Z","updated_at":"2025-03-01T15:30:38.000Z","dependencies_parsed_at":"2024-10-28T11:10:33.149Z","dependency_job_id":null,"html_url":"https://github.com/ttulka/ddd-example-ecommerce-microservices","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fddd-example-ecommerce-microservices","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fddd-example-ecommerce-microservices/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fddd-example-ecommerce-microservices/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fddd-example-ecommerce-microservices/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ttulka","download_url":"https://codeload.github.com/ttulka/ddd-example-ecommerce-microservices/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244822629,"owners_count":20516141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["architecture","ddd","docker","domain-driven-design","event-driven","example","kubernetes","microservices","oop","soa","spring-boot"],"created_at":"2024-10-12T04:13:25.994Z","updated_at":"2025-03-21T15:31:15.871Z","avatar_url":"https://github.com/ttulka.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# DDD Microservices Example Project in Java: eCommerce\n\nThe purpose of this project is to provide a sample implementation of an e-commerce product following **Domain-Driven Design (DDD)** and **Service-Oriented Architecture (SOA)** principles.\n\nProgramming language is Java with heavy use of Spring Boot, Docker and Kubernetes.\n\n## Purpose of the Project\n\nThis repository focuses mostly on cross-cutting, infrastructure and deployment concerns. \n\nFor the domain and application concepts see the [original repository](https://github.com/ttulka/ddd-example-ecommerce).\n\n## Monolith vs Microservices\n\nBoth monolithic and microservices deployments are implemented. \n\nTo run the monolithic application:\n\n```sh\n./gradlew :application:bootRun\n```\n\nTo set up and run microservices, see the [Docker](#docker-containers) and [Kubernetes](#kubernetes) sections.\n\nRead more about monoliths vs microservices at https://blog.ttulka.com/good-and-bad-monolith\n\n## Message Broker\n\nAs the message broker a simple **Redis** instance could be used with Spring profile `redis`:\n\n```sh\ndocker run --rm --name redis-broker -p 6379:6379 -d redis:6 redis-server\n\n./gradlew :application:bootRun --args='--spring.profiles.active=redis'\n```\n\nAlternatively, **RabbitMq** could be used as the message broker with Spring profile `rabbitmq`:\n\n```sh\ndocker run --rm --name rabbitmq-broker -p 5672:5672 -d rabbitmq:3\n\n./gradlew :application:bootRun --args='--spring.profiles.active=rabbitmq'\n```\n\nWhen neither `redis` not `rabbitmq` profiles are active, the system will fall-back to use of Spring application events as the default messaging mechanism.\n\n### Messaging Integration\n\nTo make the code independent of a concrete messaging implementation and easy to use, Spring application events are used for the internal communication.\n\nIn practice, this means that messages are published via `EventPublisher` abstraction and consumed via Spring's `@EventListener`.\n\nTo make this work, the external messages are re-sent as Spring application events under the hood.   \n\n## Database\n\nThe whole system uses one externalized database with particular tables owned exclusively by services.\n\nIn a real-world system this separation would be further implemented by separate schemas/namespaces.\n\nAs the database **PostgreSQL** instance could be used:\n\n```sh\ndocker run --rm --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=secret -d postgres:13\n```\n\nStart the application with Spring profile `postgres`:\n\n```sh\n./gradlew :application:bootRun --args='--spring.profiles.active=postgres'\n```\n\nWhen the `postgres` profile is not active, the system will fall-back to use H2 as the default database.\n\n## Gradle Build \n\nThe project is a Gradle multi-project, all sub-projects can be built in a single command:\n\n```sh\n./gradlew clean build\n```\n\n## Docker Containers\n\nBuild an image per microservice via Gradle Spring Boot plugin:\n```sh\n./gradlew bootBuildImage\n```\n\nTo run the containers:\n```sh\ndocker container run --rm -p 8080:8001 ttulka/ecommerce-catalog-service\ndocker container run --rm -p 8080:8002 ttulka/ecommerce-order-service\ndocker container run --rm -p 8080:8003 ttulka/ecommerce-cart-service\ndocker container run --rm -p 8080:8004 ttulka/ecommerce-payment-service\ndocker container run --rm -p 8080:8005 ttulka/ecommerce-delivery-service\ndocker container run --rm -p 8080:8006 ttulka/ecommerce-dispatching-service\ndocker container run --rm -p 8080:8007 ttulka/ecommerce-warehouse-service\ndocker container run --rm -p 8080:8000 ttulka/ecommerce-portal-service\n```\n\nActive profiles can be set as follows:\n```sh\ndocker container run --rm -e \"SPRING_PROFILES_ACTIVE=redis,postgres\" -p 8080:8001 ttulka/ecommerce-catalog-service\n```\n\n### Docker-Compose\n\nBuild NGINX reverse proxy image:\n```sh\ndocker build -t ttulka/ecommerce-reverseproxy reverseproxy\n```\n\nStart the entire microservices stack:\n```sh\ndocker-compose up\n```\n\nAccess the Postgres database and init some data:\n```sh\ndocker exec -it \u003ccontainerID\u003e psql -U postgres postgres\n```\n\n```sql\nINSERT INTO categories VALUES\n    ('C1', 'books', 'Books'),\n    ('C2', 'games', 'Games');\n\nINSERT INTO products VALUES\n    ('P1', 'Domain-Driven Design', 'by Eric Evans', 45.00),\n    ('P2', 'Object Thinking', 'by David West', 35.00),\n    ('P3', 'Chess', 'Classic game.', 3.20);\n\nINSERT INTO products_in_categories VALUES\n    ('P1', 'C1'),\n    ('P2', 'C1'),\n    ('P3', 'C2');\n\nINSERT INTO products_in_stock VALUES\n    ('P1', 5),\n    ('P2', 0),\n    ('P3', 1);\n```\n\nThe NGINX reverse proxy serves as a simple API gateway:\n```sh\ncurl localhost:8080/catalog/products\ncurl localhost:8080/warehouse/stock/5\n```\n\n## Kubernetes\n\nTo use local images for development with Minikube, run the following command to use local Docker images registry:\n```sh\nminikube start\neval $(minikube docker-env)\n```\n\nAfterwards, build the docker images again for the Minikube's Docker daemon:\n```sh\n./gradlew bootBuildImage\n```\n\nCreate deployments:\n```sh\nkubectl apply -f 1-infrastructure.k8s.yml\nkubectl apply -f 2-backend-services.k8s.yml\nkubectl apply -f 3-frontend-portal.k8s.yml\nkubectl apply -f 4-api-gateway.k8s.yml\n```\n\nSet up ports forwarding to access the cluster from your local network:\n```sh\nkubectl port-forward service/reverseproxy 8080:8080\n```\n\nAlternatively, you can create an Ingress:\n```sh\nminikube addons enable ingress\n\nkubectl apply -f 5-ingress.k8s.yml\n\n# get the ingress address \nkubectl get ingress ecommerce-ingress\n\n# add the address into hosts\nsudo cp /etc/hosts hosts.bak\nsudo echo -e '\\n\u003cingress-address\u003e ecommerce.local' \u003e\u003e /etc/hosts\n\n# access the application in browser: http://ecommerce.local\n``` \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttulka%2Fddd-example-ecommerce-microservices","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttulka%2Fddd-example-ecommerce-microservices","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttulka%2Fddd-example-ecommerce-microservices/lists"}