Building projections in CQRS/ES is easy using Java / Kotlin classes. An in-memory projections are fast, easy to-test and easy-to-debug, but they need a replay to be refilled on application restarts. On the other hand, building JPA projection allow to store data in RDBMS, but require a mapping between the in-memory object representation and relational schema.
Microstream EclipseStore allows to easily store object structure without the object-relational impedance mismatch. This project is an example showing its application.
- Created a "generic" StorageRoot to be able to put elements referenced by name inside (eager loaded)
- Created Axon Framework Token-Store using Eclipse Store as persistence
- Provided
ReadOnlyRepository<KEY, VALUE>
andFullAccessRepository<KEY, VALUE>
repositories - Provided map-based implementation for the repositories with eager loading
- Implemented a multi-bounded-context modulith
- Followed Clean Architecture approach (Onion + Hex)
- Used Axon Framework as a part of in/outbound adapter
- Followed CQRS/ES style in those adapters
- Used Axon Server as event store
- Used Eclipse-Store as the ONLY projection persistence technology
- PostgreSQL is available as backing storage for Eclipse-Store (can be switched to file-based) and for other persistence (aka Saga store)
The application is a virtual university. It contains of two main sub-domains: course and student. The course domain is about creation of courses taught in the university. Every course has a name, a time frame when it is offered and the maximum and current number of students. The student domain is about students. They can register in the university for certain time frame. A student has some personal data, time frame of registration and gets an matriculation number.
Now students can subscribe to courses. There are (on-purpose) some business rules checked:
- a student can only subscribe if the maximum number of students is not reached in the course
- a student can only subscribe if the course has not yet started
- on the course side, it is sufficient to provide the matriculation number of the student to subscribe
- on the stundet side, the course must take place during the registration time frame of the student (you must be in the university to subscribe to the course).
- Start Axon Server / PostgreSQL via
docker-compose up
- Build application with mvn (
./mvnw clean package
) - Run
EclipseStoreProjectingApplication
with Spring profiledisk
to use disk-based Eclipse Store - Run
EclipseStoreProjectingApplication
with Spring profilepostgresql
to use DB-based Eclipse Store - Open Swagger UI: [http://localhost:8091/swagger-ui/index.html] and click.
- In order to automate testing and demonstration, some scenarios are created. To run them, start the application first (as described above).
- Run
registration.http
using IDEA IntelliJ http client (This will create some courses in seasons and two students) - Run
subscription-happy.http
using IDEA IntelliJ http client (This will register "Miss Piggy" for "Physics II") - Run
subscription-wrong.http
using IDEA IntelliJ http client (This will try to register "Kermit The Frog" for "Nuclear Power I", but will fail and then compensate, because Kermit is not in the university as the course is given.)
- TODO: Create a multi-instance setup of the application with synchronized Eclipse-Store for the projections.
- TODO: provide a lazy-loading map-based repository implementation
If you find this interesting, please provide me some feedback...