This document is a collation of resources for understanding actual practical usage of the Axon Framework:
- Feel free to:
- use it to lookup something (code snippets/examples/tips).
- contribute a change if something is wrong or missing.
- fork it and make a better/derivative version.
Contents
- Project Structure (Start Here)
- Open Source Example Projects
- Examples of testing
@AggregateTips@Repository<T>Tips- Examples of snapshotting
- Tracking Event Processor
- Subscription Queries
See:
- The quick start application.
- It is based on Axon 3 but the API is more or less the same for Axon 4.
- Gives you a solid base in which you can learn:
- The typical Axon CQRS project structure.
- Axon Framework APIs (
@CommandHandler,@EventSourcingHandler,@EventHandler,@QueryHandler, etc). - Important: How to test your application (see test suite).
- The associated Webinar
- Ideal to watch at 1.5x/2x speed.
- A good walkthrough of the structure.
- nklmish/axon-casino
- Kotlin, Axon 3
- idugalic/axon-contract-testing-demo
- Java 8, Axon 4
- Demo - Axon - Bounded contexts - Saga pattern - Contract testing
- https://idugalic.github.io/axon-contract-testing-demo/
- idugalic/axon-polymorphism-demo
- Java 8, Axon 4
- Axon and OOP (Inheritance, Polymorphism)
- AxonIQ/axon-quick-start
- Java 8, Axon 4
- Repository containing some base code and guidelines to build and then scale an application
- idugalic/axon-scale-demo
- Java 8, Axon 4
- Axon (Spring Boot) demo application - Deploy to Kubernetes via Docker Stack API and/or
kubectlandskaffold- Scale out - https://idugalic.github.io/axon-scale-demo/
- gushakov/axon-simple
- Java 8, Axon 4
- Simple CQRS application using Axon without Event Sourcing
- idugalic/axon-statemachine-demo
- Java 8, Axon 4
- This demo application demonstrate the usage of inheritance and polymorphism for making the concept of the finite state machine more explicit in your design.
- fransvanbuul/axon-sync-rest-frontend
- Java 8, Axon 3
- Small example illustrating how to create a synchronous REST front-end on an asynchronous CQRS+ES back-end using Axon's subscription queries.
- AxonFramework/Axon-trader
- Java 8, Axon 3
- Sample application to demonstrate the possibilities of the Axon framework in a high load environment.
- AxonFramework/AxonBank
- Java 8, Axon 3
- This is a sample application with the purpose of showing the capabilities of Axon Framework.
- AxonIQ/conference-demo-bike-rental
- Java 8, Axon 3
- Digital Restaurant:
- idugalic/digital-restaurant
- Kotlin, Axon 4
- idugalic/digital-restaurant-angular
- It is a front-end part of a 'Restaurant Food To Go' solution. It consumes REST API provided by https://github.com/idugalic/digital-restaurant/drestaurant-apps/drestaurant-monolith
- idugalic/digital-restaurant
- haschi/dominium
- Kotlin, Axon 3
- Accounting system for households. A playground to practice Domain Driven Design and CQRS / ES with Axon Framework
- AxonIQ/food-ordering-demo
- Java 8, Axon 4
- Demo application focusing on the Food Ordering domain - Used in our video series
- AxonIQ/giftcard-demo
- Java 11, Axon 4
- This Axon Framework demo application focuses around a simple giftcard domain, designed to show various aspects of the framework.
- AxonIQ/hotel-demo
- Java 11, Axon 4
- It's the implementation of the example used in this blog post: https://eventmodeling.org/posts/what-is-event-modeling/
- croz-ltd/klokwrk-project
- Groovy, Axon
- https://croz.net/news/introducing-project-klokwrk/
- idugalic/micro-company
- Java 8, Axon 3
- Intended to demonstrate end-to-end best practices for building a cloud native, event driven microservice architecture using Spring Cloud and Axon
- idugalic/axon-vanilla-java-demo
- Java 8, Axon 4
- Demonstrates use of Axon (vanilla Java) Configuration API with Axon Server.
- matty-matt/movie-keeper-core
- Java 11, Axon 4
- Backend for MovieKeeper React application that allows storing movies you'd like to watch. Digital release dates of your stored movies are tracked by app.
- AxonIQ/running-axon-server
- The files that go with the "Running Axon Server" Blog series:
- AxonIQ/code-samples
- Contains a number of subprojects with each subproject showcasing example code for a specific scenario:
- axon-spring-template
- distributed-exceptions
- reset-handler
- saga
- sequencing-policy
- set-based-validation
- subscription-query-rest
- subscription-query-ui-streaming
- upcaster
- Contains a number of subprojects with each subproject showcasing example code for a specific scenario:
- JohT/showcase-quarkus-eventsourcing
- Java 11, Axon 4
- Shows an example on how to use axon in conjunction with microprofile on quarkus
- fransvanbuul/sq-webinar
- Java 8, Axon 3
- Repository of the live code webinar on subscription queries - 24 July 2018
- Introducing Subscription Queries - AxonIQ Webinar
- abuijze/webinar-axon-bank
- Java 8, Axon 3
- Unit Testing an
@Aggregate:
See:
Occasionally, we need to write a @Component which has access to an underlying Axon Repository<T>.
- Sometimes dealing with a
@Repository<T>can be slightly annoying (I think it is because of the generic type<T>). - Follow the tips in the code snippets below when you have a problem.
- You need to add a
@Lazyto the parameter in the constructor in your@Component(assuming constructor injection and all final fields). - If you do not do this your application context may fail to load because of an NPE.
@Bean
public Repository<GiftCard> giftCardRepository(EventStore eventStore, Cache cache) {
return EventSourcingRepository.builder(GiftCard.class)
.cache(cache)
.eventStore(eventStore)
.build();
}For original code source, see: giftcard-demo.
The digital restaurant application contains examples of how to define snapshotting for your aggregates From the README:
A Snapshot is a denormalization of the current state of an aggregate at a given point in time
It represents the state when all events to that point in time have been replayed
They are used as a heuristic to prevent the need to load all events for the entire history of an aggregate
Each aggregate defines a snapshot trigger:
@Aggregate(snapshotTriggerDefinition = "courierSnapshotTriggerDefinition")
Feel free to configure a treshold (number of events) that should trigger the snapshot creation. This treshold is externalized as a property axon.snapshot.trigger.treshold.courier
Courier@Aggregate:CourierOrder@Aggregate:Customer@Aggregate:CustomerOrder@Aggregate:
Examples of configuring tracking event processors:
See:
- idugalic/axon-scale-demo:
- GiftCardHandler
@Component(@ProcessingGroup("giftcardprocessor")) - application.properties
- We set
mode=tracking,initial-segment-count=4,thread-count=4
- We set
- GiftCardHandler
See:
(Kotlin) nklmish/axon-casino:
- Example 1:
- SingleWalletSummaryQuery Subscription Query (line 167):
val queryResult = queryGateway.subscriptionQuery( SingleWalletSummaryQuery(cmd.walletId), // 1 ResponseTypes.instanceOf(WalletSummary::class.java), // 2 ResponseTypes.instanceOf(WalletSummaryUpdate::class.java)) // 3
- 1: Subscribe to
SingleWalletSummaryQuery. - 2: Initial subscription will return the response type:
ResponseTypes.instanceOf(WalletSummary::class.java) - 3: Subsequent updates in the subscription will be of the response type:
ResponseTypes.instanceOf(WalletSummaryUpdate::class.java)
- 1: Subscribe to
- SingleWalletSummaryQuery
@QueryHandler:- Provides the initial result to the
SingleWalletSummaryQuerysubscription query. - This initial result is of type:
WalletSummary.
- Provides the initial result to the
- SingleWalletSummaryQuery queryUpdateEmitter.emit(..):
- Provides the subsequent updates to the
SingleWalletSummaryQuerysubscription query. - These are updates are of the type
WalletSummaryUpdate. - There are multiple
@EventHandlerswhich do this.- Search for
queryUpdateEmitter.emit(on the page to see them e.g. line 41, 49, 58, etc.
- Search for
- Provides the subsequent updates to the
- SingleWalletSummaryQuery Subscription Query (line 167):
- Example 2:
- TotalDepositedQuery Subscription Query (line 20):
return queryGateway.subscriptionQuery(TotalDepositedQuery(), // 1 ResponseTypes.multipleInstancesOf(TotalDepositedSample::class.java), // 2 ResponseTypes.instanceOf(TotalDepositedSample::class.java)).updates() // 3
- 1: Subscribe to
TotalDepositedQuery. - 2: Initial subscription will return the response type:
ResponseTypes.multipleInstancesOf(TotalDepositedSample::class.java) - 3: Subsequent updates in the subscription will be of the response type:
ResponseTypes.instanceOf(TotalDepositedSample::class.java)
- 1: Subscribe to
- TotalDepositedQuery
@QueryHandler:- Provides the initial result to the
TotalDepositedQuerysubscription query. - This initial result is of type:
List<TotalDepositedSample>.
- Provides the initial result to the
- TotalDepositedQuery queryUpdateEmitter.emit(..):
- Provides the subsequent updates to the
TotalDepositedSamplesubscription query. - These are updates are of the type
TotalDepositedSample.
- Provides the subsequent updates to the
- TotalDepositedQuery Subscription Query (line 20):
(Java) fransvanbuul/sq-webinar:
FetchCardSummariesQuerySubscription Query:return queryGateway.subscriptionQuery( new FetchCardSummariesQuery(0,1, new CardSummaryFilter("")), // 1 ResponseTypes.multipleInstancesOf(CardSummary.class), // 2 ResponseTypes.instanceOf(CardSummary.class)).updates(); // 3
- 1: Subscribe to
FetchCardSummariesQuery. - 2: Initial subscription will return the response type:
ResponseTypes.multipleInstancesOf(CardSummary.class) - 3: Subsequent updates in the subscription will be of the response type:
ResponseTypes.instanceOf(CardSummary.class)
- 1: Subscribe to
- FetchCardSummariesQuery
@QueryHandler:- Provides the initial result to the
FetchCardSummariesQuerysubscription query. - The initial result is of type:
List<CardSummary>
- Provides the initial result to the
- FetchCardSummariesQuery queryUpdateEmitter.emit(..):
- Provides the subsequent updates to the
FetchCardSummariesQuerysubscription query. - These are updates are of the type
CardSummary.
- Provides the subsequent updates to the
(Kotlin) idugalic/digital-restaurant:
- Lots of examples in this repo.