{"id":13753068,"url":"https://github.com/idugalic/micro-company","last_synced_at":"2025-04-09T05:11:44.126Z","repository":{"id":44671546,"uuid":"56147007","full_name":"idugalic/micro-company","owner":"idugalic","description":"Rest-full, Hipermedia-based distributed application. Spring boot \u0026 cloud. Angular. CQRS. Eventsourcing. Axonframework. Microservices. Docker. CloudFoundry ","archived":false,"fork":false,"pushed_at":"2024-09-15T09:56:23.000Z","size":4540,"stargazers_count":351,"open_issues_count":8,"forks_count":139,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-04-02T04:04:21.387Z","etag":null,"topics":["architecture","aws","axon","axon-framework","cloudfoundry","cqrs","demo","docker","docker-swarm","event-sourcing","java","microservice","spring","spring-boot","spring-cloud"],"latest_commit_sha":null,"homepage":"http://idugalic.github.io/micro-company","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idugalic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2016-04-13T11:43:49.000Z","updated_at":"2025-02-25T12:25:29.000Z","dependencies_parsed_at":"2024-08-03T09:05:01.335Z","dependency_job_id":"26212f7a-7c58-48b5-a584-183d46ce7587","html_url":"https://github.com/idugalic/micro-company","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/idugalic%2Fmicro-company","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Fmicro-company/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Fmicro-company/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Fmicro-company/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idugalic","download_url":"https://codeload.github.com/idugalic/micro-company/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247980844,"owners_count":21027808,"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","aws","axon","axon-framework","cloudfoundry","cqrs","demo","docker","docker-swarm","event-sourcing","java","microservice","spring","spring-boot","spring-cloud"],"created_at":"2024-08-03T09:01:15.683Z","updated_at":"2025-04-09T05:11:44.107Z","avatar_url":"https://github.com/idugalic.png","language":"JavaScript","funding_links":[],"categories":["spring-cloud","📦 Legacy \u0026 Inactive Projects"],"sub_categories":[],"readme":"# [projects](http://idugalic.github.io/projects)/micro-company ![Java CI with Maven](https://github.com/idugalic/micro-company/workflows/Java%20CI%20with%20Maven/badge.svg?branch=master)\n\nThis project is intended to demonstrate end-to-end best practices for building a cloud native, event driven microservice architecture using [Spring Cloud](https://spring.io/projects/spring-cloud) and [Axon](https://axoniq.io/).\n\n## Table of Contents\n\n   * [Application 'Micro Company'](#application-micro-company-)\n      * [What is cloud native](#what-is-cloud-native)\n      * [Architecture](#architecture)\n         * [Patterns and techniques:](#patterns-and-techniques)\n         * [Technologies](#technologies)\n         * [Key benefits](#key-benefits)\n         * [How it works](#how-it-works)\n         * [Services](#services)\n            * [Backing services](#backing-services)\n               * [(Service) Registry](#service-registry)\n               * [Authorization server (Oauth2)](#authorization-server-oauth2)\n               * [Configuration server](#configuration-server)\n               * [API Gateway](#api-gateway)\n            * [Backend Microservices](#backend-microservices)\n               * [BlogMicroservice](#blogmicroservice)\n               * [ProjectMicroservice](#projectmicroservice)\n               * [Admin server (\u003ca href=\"http://codecentric.github.io/spring-boot-admin/1.3.2/\"\u003ehttp://codecentric.github.io/spring-boot-admin/1.3.2/\u003c/a\u003e)](#admin-server-httpcodecentricgithubiospring-boot-admin132)\n      * [Running instructions](#running-instructions)\n         * [Prerequisite](#prerequisite)\n         * [Step 1: Clone the project](#step-1-clone-the-project)\n         * [Step 2 (Optional): Build the project](#step-2-optional-build-the-project)\n            * [Build the project](#build-the-project)\n            * [Build docker images via maven](#build-docker-images-via-maven)\n         * [Step 3: Run the application as](#step-3-run-the-application-as)\n            * [Run monolithic on localhost](#run-monolithic-on-localhost)\n               * [Docker](#docker)\n               * [Maven](#maven)\n               * [Eclipse](#eclipse)\n            * [Run microservices on localhost via docker](#run-microservices-on-localhost-via-docker)\n            * [Run microservices on Docker Swarm (mode) - Local cluster](#run-microservices-on-docker-swarm-mode---local-cluster)\n            * [Run microservices on Docker Swarm (mode) - AWS cluster](#run-microservices-on-docker-swarm-mode---aws-cluster)\n            * [Run microservices on Pivotal Cloud Foundry - PCF Dev](#run-microservices-on-pivotal-cloud-foundry---pcf-dev)\n               * [CLI](#cli)\n               * [Eclipse](#eclipse-1)\n         * [Issuing Commands \u0026amp; Queries with CURL](#issuing-commands--queries-with-curl)\n            * [Create Blog post](#create-blog-post)\n                  * [Microservices](#microservices)\n                  * [Monolithic](#monolithic)\n            * [Publish Blog post](#publish-blog-post)\n                  * [Microservices](#microservices-1)\n                  * [Monolithic](#monolithic-1)\n            * [Query Blog posts](#query-blog-posts)\n                  * [Microservices](#microservices-2)\n                  * [Monolithic](#monolithic-2)\n            * [Create Project](#create-project)\n                  * [Microservices](#microservices-3)\n                  * [Monolithic](#monolithic-3)\n            * [Query Projects](#query-projects)\n                  * [Microservices](#microservices-4)\n                  * [Monolithic](#monolithic-4)\n            * [WebSocket on the gateway](#websocket-on-the-gateway)\n                  * [Microservices](#microservices-5)\n      * [About AXON](#about-axon)\n         * [Commands](#commands)\n         * [Events](#events)\n         * [Domain](#domain)\n         * [Repositories](#repositories)\n         * [Event Stores](#event-stores)\n         * [Event Bus](#event-bus)\n         * [Sagas](#sagas)\n         * [Testing](#testing)\n         * [Spring support](#spring-support)\n      * [References and further reading](#references-and-further-reading)\n\n## What is cloud native\n\nTo understand “cloud native,” we must first understand “cloud.”\nIn the context of this application, cloud refers to Platform as a Service. PaaS providers expose a platform that hides infrastructure details from the application developer, where that platform resides on top of Infrastructure as a Service (IaaS). \n\nA cloud-native application is an application that has been designed and implemented to run on a Platform-as-a-Service installation and to embrace horizontal elastic scaling.\n\n## Architecture\n\nThe microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API or via events (event-driven).\n\nMicroservices enable businesses to innovate faster and stay ahead of the competition. But one major challenge with the microservices architecture is the management of distributed data. Each microservice has its own private database. It is difficult to implement business transactions that maintain data consistency across multiple services as well as queries that retrieve data from multiple services.\n\n![Microservice Architecture - Ivan Dugalic](micro-company.PNG)\n\n### Patterns and techniques:\n\n1. Microservices\n2. Command and Query Responsibility Separation (CQRS)\n3. Event Sourcing\n4. DDD - Agregates\n\n### Technologies\n\n- [Spring Boot](http://projects.spring.io/spring-boot/) (v1.5.3.RELEASE)\n- [Spring Cloud](http://projects.spring.io/spring-cloud/) (Dalston.RELEASE)\n- [Spring Data](http://projects.spring.io/spring-data/) (train: Ingalls-SR3)\n- [Spring Data REST](http://projects.spring.io/spring-data-rest/)\n- [Axon Framework](http://www.axonframework.org/) (v3.0.4)\n- [RabbitMQ](https://www.rabbitmq.com/) (v3.5.4) Axon supports any Spring AMQP supported platform.\n- [Docker](https://www.docker.com/) (v17.05.0-ce-mac11)\n\n\n### Key benefits\n\n1. Easy implementation of eventually consistent business transactions that span multiple microservices\n2. Automatic publishing of events whenever data changes\n3. Faster and more scalable querying by using materialized views\n4. Reliable auditing for all updates\n\n\n### How it works\n\nThe domain is literally split into a *command-side* microservice application and a *query-side* microservice application (this is CQRS in its most literal form).\n\nCommunication between the two microservices is `event-driven` and the demo uses RabbitMQ messaging as a means of passing the events between processes (VM's).\n\nThe **command-side** processes commands. Commands are actions which change state in some way. The execution of these commands results in `Events` being generated which are persisted by Axon  and propagated out to other VM's (as many VM's as you like) via RabbitMQ messaging. In event-sourcing, events are the sole records in the system. They are used by the system to describe and re-build aggregates on demand, one event at a time.\n\nThe **query-side** is an event-listener and processor. It listens for the `Events` and processes them in whatever way makes the most sense. In this application, the query-side just builds and maintains a *materialised view* which tracks the state of the individual agregates (Product, Blog, Customer, ...). The query-side can be replicated many times for scalability and the messages held by the RabbitMQ queues are durable, so they can be temporarily stored on behalf of the event-listener if it goes down.\n\nThe command-side and the query-side both have REST API's which can be used to access their capabilities.\n\nRead the [Axon documentation](https://docs.axoniq.io/reference-guide/) for the finer details of how Axon generally operates to bring you CQRS and Event Sourcing to your apps, as well as lots of detail on how it all get's configured.\n\n### Services\n\n#### Backing services\n\nThe premise is that there are third-party service dependencies that should be treated as attached resources to your cloud native applications. The key trait of backing services are that they are provided as bindings to an application in its deployment environment by a cloud platform.\nEach of the backing services must be located using a statically defined route\n\n##### (Service) Registry\nNetflix Eureka is a service registry. It provides a REST API for service instance registration management and for querying available instances. Netflix Ribbon is an IPC client that works with Eureka to load balance(client side) requests across the available service instances.\n\n##### Authorization server (Oauth2)\nFor issuing tokens and authorize requests.\n\n##### Configuration server\nThe configuration service is a vital component of any microservices architecture. Based on the twelve-factor app methodology, configurations for your microservice applications should be stored in the environment and not in the project.\nConfiguration is hosted here: https://github.com/idugalic/micro-company-config.git\n\n##### API Gateway\nImplementation of an API gateway that is the single entry point for all clients. The API gateway handles requests in one of two ways. Some requests are simply proxied/routed to the appropriate service. It handles other requests by fanning out to multiple services.\n\n\n#### Backend Microservices\n\nWhile the backing services in the middle layer are still considered to be microservices, they solve a set of concerns that are purely operational and security-related. The business logic of this application sits almost entirely in our bottom layer.\n\n##### BlogMicroservice\nA Blog service is used for manging and quering the posts of your company. It is split into a *command-side* microservice application and a *query-side* microservice application.\n\n##### ProjectMicroservice\nA Project service is used for manging and quering the projects of your company. It is split into a *command-side* microservice application and a *query-side* microservice application.\n\n##### Admin server (http://codecentric.github.io/spring-boot-admin/1.3.2/)\nSpring Boot Admin is a simple application to manage and monitor your Spring Boot services. The services are discovered using Spring Cloud (e.g. Eureka). The UI is just an Angular.js application on top of the Spring Boot Actuator endpoints. In case you want to use the more advanced features (e.g. jmx-, loglevel-management), Jolokia must be included in the client services.\n\nPlease note that this server/service could fit to 'Backing services' as well. In this case all services would use Admin Client to connect to this service (and not Eureka).\n\n\n## Running instructions\n\n### Prerequisite\n\n- [Java JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)\n- [Git](https://git-scm.com/) \n- [Docker](https://www.docker.com/)\n- VirtualBox\n\n### Step 1: Clone the project\n\n```bash\n$ git clone https://github.com/idugalic/micro-company.git\n```\n\n### Step 2 (Optional): Build the project\nPlease note that images are available on the docker hub (https://hub.docker.com/u/idugalic), so if you do not want to build the services, simply skip to Step 3\n\n#### Build the project\n \n```bash\n$ cd micro-company\n$ mvn clean install\n```\n\n#### Build docker images via maven\n\n```bash\n$ DOCKER_HOST=unix:///var/run/docker.sock mvn docker:build\n```\n\nor to build and push images via maven (requires username and password of docker repo):\n\n```bash\n$ DOCKER_HOST=unix:///var/run/docker.sock mvn docker:build -DpushImage\n```\n### Step 3: Run the application as\n\n- monolithic on localhost or\n- microservices on localhost via docker or\n- microservices on docker swarm (mode) - local cluster\n- microservices on docker swarm (mode) - AWS cluster\n- microservices on Pivotal Cloud Foundry - PCF Dev\n\n#### Run monolithic on localhost\n\nThis version of the application is deployed as a single monolithic application.\n\nDomain Driven Design is applied through Event Sourcing and CQRS. How Event Sourcing enables deployment flexibility - the application can be deployed as a monolith.\n\nThe domain is literally split into a command-side component and a query-side component (this is CQRS in its most literal form).\n\nCommunication between the two components is event-driven and the demo uses simple event store (Database in this case - JPA) as a means of passing the events between components. RabbitMQ is not needed in this case.\n\n\n##### Docker\n```bash\n$ cd micro-company/docker\n$ docker-compose -f docker-compose-monolithic.yml up -d \n```\n##### Maven\n```bash\n$ cd micro-company\n$ mvn clean install\n$ cd micro-company/monolithic\n$ mvn spring-boot:run\n```\n##### Eclipse\nRun as Spring Boot Project. \nI can advice for Boot Dashboard to be used as well.\n\n#### Run microservices on localhost via docker\n\n```bash\n$ cd micro-company/docker\n$ docker-compose up -d \n```\n\n#### Run microservices on Docker Swarm (mode) - Local cluster\n\nDocker Engine 1.12+ includes swarm mode for natively managing a cluster of Docker Engines called a swarm. https://docs.docker.com/engine/swarm\n\n```bash\n$ cd micro-company/docker\n$ . ./swarm-mode-local.sh\n```\nBy executing this script you will:\n\n- create 4 virtual machines (VirtualBox is required). One 'swarm master', and three 'swarm nodes'\n- initialize cluster on the swarm master\n- join nodes to the cluster\n- deploy services using a `docker-compose.yml` file directly\n\nPlease, follow the instructions in the console log, and have fun :)\n\n##### Experimental features\n\n- Aggregated logs of a service\n- Docker build has a new experimental --squash\n\nIn version 1.13 the experimental features are now part of the standard binaries and can be enabled by running the Deamon with the --experimental flag. Let’s do just this. First we need to change the dockerd profile and add the flag:\n```bash\n$ docker-machine ssh swmaster -t sudo vi /var/lib/boot2docker/profile\n```\nadd the --experimental flag to the EXTRA_ARGS variable. In my case the file looks like this after the modification\n```\nEXTRA_ARGS='\n--label provider=virtualbox\n--experimental\n\n'\n```\nSave the changes as reboot the leader node:\n```bash\ndocker-machine stop swmaster\ndocker-machine start swmaster\n```\n\n#### Run microservices on Docker Swarm (mode) - AWS cluster\n\nDocker Engine 1.12+ includes swarm mode for natively managing a cluster of Docker Engines called a swarm. https://docs.docker.com/engine/swarm\n\nWe will deploy services on AWS infrastucture. You have to prepare it.\nPlease note that steps 1 and 3 are optional. You don't have to create users or key pars if you already have them.\n\n- Step 1: Login to your AWS account as a root, and create user (not root) that will be used latter. Follow the [guide.](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html#id_users_create_console)\n- Step 2: [Login](https://signin.aws.amazon.com/console/) with your new user account.\n- Step 3: [Create Your Key Pair Using Amazon EC2.](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html#having-ec2-create-your-key-pair) Please note that the key will be downloaded by the browser. In my case it is '/Users/idugalic/.ssh/idugalic.pem'.\n- Step 4: Create stack on AWS by using [CloudFormation template](https://console.aws.amazon.com/cloudformation/home#/stacks/new?stackName=Docker\u0026templateURL=https://editions-us-east-1.s3.amazonaws.com/aws/stable/Docker.tmpl)\n- Step 5: Run the shell script bellow and follow instructions.\n\n```bash\n$ cd micro-company/docker\n$ . ./swarm-mode-aws.sh\n```\n\n#### Run microservices on Pivotal Cloud Foundry - PCF Dev\nRun services on local workstation with PCF Dev\n\n- Download and install PCF: https://pivotal.io/platform/pcf-tutorials/getting-started-with-pivotal-cloud-foundry-dev/introduction\n- Start PCF Dev: `$ cf dev start -m 8192 `\n- Login to PCF Dev\" `$ cf login -a https://api.local.pcfdev.io --skip-ssl-validation -u admin -p admin -o pcfdev-org`\n- Create user service - configserver: `$ cf cups configserver -p '{\"uri\":\"http://configserver.local.pcfdev.io\"}'`\n- Create user service - registry: `$ cf cups registry -p '{\"uri\":\"http://registry.local.pcfdev.io\"}'`\n- Create user service - authserver: `$ cf cups authserver -p '{\"uri\":\"http://authserver.local.pcfdev.io\"}'`\n- Create cloud foundry service instance - mysql: `$ cf create-service p-mysql 512mb mysql`\n- Create cloud foundry service instance - rabbit: `$ cf create-service p-rabbitmq standard rabbit`\n- Open your browser and point to https://local.pcfdev.io. Explore !\n\n\n##### CLI\nPush microservices in command line:\n\n```bash\n$ cd micro-company/\n$ mvn clean install\n$ cf push -f configserver/manifest.yml -p configserver/target/configserver-0.0.1-SNAPSHOT.jar\n$ cf push -f registry/manifest.yml -p registry/target/registry-0.0.1-SNAPSHOT.jar\n$ cf push -f authserver/manifest.yml -p authserver/target/authserver-0.0.1-SNAPSHOT.jar\n$ cf push -f command-side-blog-service/manifest.yml -p command-side-blog-service/target/command-side-blog-service-0.0.1-SNAPSHOT.jar\n$ cf push -f command-side-project-service/manifest.yml -p command-side-project-service/target/command-side-project-service-0.0.1-SNAPSHOT.jar\n$ cf push -f query-side-blog-service/manifest.yml -p query-side-blog-service/target/query-side-blog-service-0.0.1-SNAPSHOT.jar\n$ cf push -f query-side-project-service/manifest.yml -p query-side-project-service/target/query-side-project-service-0.0.1-SNAPSHOT.jar\n$ cf push -f api-gateway/manifest.yml -p api-gateway/target/api-gateway-0.0.1-SNAPSHOT.jar\n$ cf push -f adminserver/manifest.yml -p adminserver/target/adminserver-1.3.3.RELEASE.jar\n\n```\n\n##### Eclipse\nPush microservices with 'Boot Dashboard':\n\n- Add local (dev) cloud foundry target (https://api.local.pcfdev.io).\n- Once you are connected, start dragging the projects to this instance.\n\n\nNOTE: Please run 'configserver' first, followed by 'registry' and other services.\n\n### Issuing Commands \u0026 Queries with CURL\n\n#### Create Blog post\n\n###### Microservices\n\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"title\":\"xyz\",\"rawContent\":\"xyz\",\"publicSlug\": \"publicslug\",\"draft\": true,\"broadcast\": true,\"category\": \"ENGINEERING\", \"publishAt\": \"2016-12-23T14:30:00+00:00\"}' http://127.0.0.1:9000/command/blog/blogpostcommands \n\n```\nor on the PCF:\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"title\":\"xyz\",\"rawContent\":\"xyz\",\"publicSlug\": \"publicslug\",\"draft\": true,\"broadcast\": true,\"category\": \"ENGINEERING\", \"publishAt\": \"2016-12-23T14:30:00+00:00\"}' api-gateway.local.pcfdev.io/command/blog/blogpostcommands \n```\n###### Monolithic\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"title\":\"xyz\",\"rawContent\":\"xyz\",\"publicSlug\": \"publicslug\",\"draft\": true,\"broadcast\": true,\"category\": \"ENGINEERING\", \"publishAt\": \"2016-12-23T14:30:00+00:00\"}' http://127.0.0.1:8080/api/blogpostcommands\n\n```\n\n#### Publish Blog post\n\n###### Microservices\n\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"publishAt\": \"2016-12-23T14:30:00+00:00\"}' http://127.0.0.1:9000/command/blog/blogpostcommands/{id}/publishcommand\n\n```\n###### Monolithic\n\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"publishAt\": \"2016-12-23T14:30:00+00:00\"}' http://127.0.0.1:8080/api/blogpostcommands/{id}/publishcommand\n\n```\n\n#### Query Blog posts\n\n###### Microservices\n\n```bash\n$ curl http://127.0.0.1:9000/query/blog/blogposts\n```\nor on the PCF:\n```bash\n$ curl api-gateway.local.pcfdev.io/query/blog/blogposts\n```\n###### Monolithic\n```bash\n$ curl http://127.0.0.1:8080/api/blogposts\n```\n\n#### Create Project\n\n###### Microservices\n\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"name\":\"Name\",\"repoUrl\":\"URL\",\"siteUrl\": \"siteUrl\",\"description\": \"sdfsdfsdf\"}' http://127.0.0.1:9000/command/project/projectcommands\n\n```\n###### Monolithic\n\n```bash\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"name\":\"Name\",\"repoUrl\":\"URL\",\"siteUrl\": \"siteUrl\",\"description\": \"sdfsdfsdf\"}' http://127.0.0.1:8080/api/projectcommands\n\n```\n#### Query Projects\n\n###### Microservices\n \n ```bash\n$ curl http://127.0.0.1:9000/query/project/projects\n```\n###### Monolithic\n```bash\n$ curl http://127.0.0.1:8080/api/projects\n```\n\n#### WebSocket on the gateway\n\n###### Microservices\nAll the events will be sent to browser via WebSocket and displayed on http://127.0.0.1:9000/socket/index.html\nor on the PCF: http://api-gateway.local.pcfdev.io/socket/index.html\n\n\n## About AXON\n\n### Commands \n\nCommands are messages that are sent to a system with an intent of doing something. They are sent to a Command Gateway, and then a Command Bus dispatches them to concrete Command Handlers. There can be some validation, or security check done in some Interceptors. The Command should be executed in some Unit of Work, which can be implemented over database transaction. Additionally Command processing may be distributed across many nodes with JGroups.\n\nAxon provides interfaces, implementation and annotations for each one of those concepts. You just need to write your Command classes, and simple Handler classes with one annotation and that's it.\n\nThere are some default Interceptors already written - like Interceptor for JSR 303 Bean Validation. If you need, you can easily write your Interceptor by implementing one simple interface.\n\n### Events\n\nAs stated before, Commands are messages with intent of doing something. On the other hand, after this something is done, another messages can be produced as a result - Events. They represent a fact.\n\nIn Axon, you just need to write your own Event classes. All the infrastructure that is responsible for handling them is there for you. In previous version (1.3) you had to extend base Event class - in current version (2.0) you don't have to do it anymore. Because of that, you can use your Events to integrate with other, non-Axon-based systems easily.\n\n### Domain\n\nYou should model your domain very carefully. This is the place, where the essential complexity lays. There are no frameworks that can help you with that. You should spend most of your time in that place.\n\nThanks to Axon, you can actually do it that way. All the infrastructure code is there for you. The one thing that Axon gives you to help you struggling with the domain modeling is base Aggregate Root class, which you can extend and get access to some useful methods.\n\nIn the end, if you are using Event Sourcing, you can use Abstract Annotated Aggregate Root and use annotations on your private methods, that are applying events and changing the state of the Aggregate. Axon will additionally dispatch Events to annotated Entities in the Aggregate.\n\nYou should not change the state of the Aggregate in methods that are not reacting on Events. This is normal in Event Sourcing. Axon guards you not to violate this principle, so an inexperienced person won't break anything.\n\n### Repositories\n\nAggregates are stored in Repositories. You should be able to load Aggregate by id, and save it back. It doesn't matter if you are using SQL database, flat files, or other noSQL solution. The persistance technique should be separated from the concept.\n\nAxon gives you this separation. You can choose to use classic JPA-based Repository, or Event Sourced Repository. It additionally adds possibility to use caching for performance tuning.\n\n### Event Stores\n\nIf you choose to use Event Sourcing, you need to store effectively your Events in some Event Store.\n\nAxon gives you an interface for Repository, and a couple of implementations. The simplest implementation is based on flat files, but it is not that powerfull as others. You can also use JPA-based Event Store, which will create only two tables - for Event entries and for Aggregate Snapshot entries. For those two solutions, you will need to serialize your Events. Axon by default uses XStream, but you can choose any other. The third Event Store is implemented over MongoDB. If you need, you can easily implement any other Event Store on your own.\n\nWhen your Aggregates live for a very long time, they can have a quite long history. For performance reasons you can use Aggregate Snapshotting to shorten the time of Aggregate loading.\n\nYour Events definition may change over the time, so those Event Stores by default give you a possibility to easily write Event Upcasters. It also gives you a support for some advanced conflict resolution when it happens. \n\n### Event Bus \n\nIn CQRS, after Events are generated, they need to be processed to update the query database. They are dispatched to Event Handlers. Those Event Handlers can be located on the same machine, or distributed in a cluster.\n\nIn Axon you just need to annatote methods of components that are supposed to listen for Events. You can also choose if you want to process Events synchronously, or asynchronously.\n\nIf some error occurs, you can define how to react. Axon can rollback transaction if you are using any, or it can reschedule the Event and process it again after some time for you. If you need any other error handling procedure, you can write it on your own by implementing simple interface. \n\nIf you have distributed environment, Axon gives you support for Spring AMQP.\n\nSometimes you need to replay historical Events, and Axon also gives you the support for doing that.\n\n### Sagas\n\nSometimes your transactions need to live longer. You cannot always finish all the work you need in a single ACID transaction. That is where Sagas come into play. On the other hand, you can use Sagas as a Workflow, or State Machine.\n\nIn Axon, Saga is a special Event Handler that handles the long business transaction. You can use Abstract Annotated Saga as a base class for your Sagas and then just use annotations on your methods that handle Events.\n\nIf you need to take care about time, or deadlines, Axon provides Sagas with Schedulers that can handle time management. You can use Simple Scheduler that uses pure Java implementation, or Quartz Scheduler that is much more powerfull.\n\n### Testing \n\nYou should test the code that you write, right? You can do it in a normal way, with mocks, or something like this, but if you are using Event Sourcing, you have another possibility. You have a history of Events, then you execute some Command, and a bunch of Events is generated as a result. You can test exactly that way with Axon.\n\nAxon gives you a Given When Then Fixture. As Given you specify historical set of Events, as When you specify a Command that is tested, and as a Then you specify full set of Events that are supposed to be generated. Everything is wired for you, and you just need to define test scenario with those Events and Command.\n\nOf course, you should also test your Sagas. There is a special Annotated Saga Test Fixture for that. As Given you specify a set of historical Event, as When you specify a single Event, and as Then you specify a desired behavior, or state change. If you need, you can also mock the time for testing time-related Sagas.\n\n### Spring support \n\nThose days, each mature framework in Java world should have some sort of Spring support. Each of Axon's components can be configured as a Spring bean. Axon provides also a namespace shortcut for almost everything it has, so the configuration is as short as it has to be.\n\n## The lab\nThis project has been migrated to a github organization http://ivans-innovation-lab.github.io/. There we can practice the Twelve-Factor App methodology.\n\nYou will learn how we:\n\n- made decisions to use one pattern against the other,\n- changed architecture, organization (culture) and process over time to respond to new requirements,\n- made a foundation for successful digitalization.\n\nThe ultimate goal is to deliver better software faster. Today, that invariably means continuous delivery – for an installed product – or continuous deployment for an -aaS product.\n\nThe source code is hosted on Github: https://github.com/ivans-innovation-lab\n\n## References and further reading\n\n  * http://martinfowler.com/articles/microservices.html\n  * http://microservices.io/\n  * http://12factor.net/\n  * http://pivotal.io/platform/migrating-to-cloud-native-application-architectures-ebook\n  * http://pivotal.io/beyond-the-twelve-factor-app\n  * http://www.infoq.com/news/2016/01/cqrs-axon-example\n  * https://www.infoq.com/articles/microservices-aggregates-events-cqrs-part-2-richardson\n  * https://axoniq.io/\n  * http://blog.arungupta.me/deploy-docker-compose-services-swarm/\n  * http://www.kennybastani.com/2016/04/event-sourcing-microservices-spring-cloud.html\n  * https://benwilcock.wordpress.com/2016/06/20/microservices-with-spring-boot-axon-cqrses-and-docker/\n  \n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidugalic%2Fmicro-company","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidugalic%2Fmicro-company","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidugalic%2Fmicro-company/lists"}