ddd-cqrs-4-java-example
Minimal standalone example application that uses the ddd-4-java and cqrs-4-java libraries and an EventStore to store the events (Event Sourcing). The query data is stored in-memory using a HSQLDB.
Starting the demo
- Start an EventStore locally on your PC
- You can use the EventStore Docker Image:
docker run --name eventstore-node -p 2113:2113 -p 1113:1113 --rm eventstore/eventstore:release-5.0.9 - Or simply start an instance (See Install and run Event Store for more information)
- You can use the EventStore Docker Image:
- Run the QryExampleApp to make the view/read part listen to new events
- You should see something like this on the console:
INFO o.f.d.qry.handler.QryProjector - Create projection 'qry-person-stream' with events: [PersonCreatedEvent] - If you open the event store UI (http://localhost:2113/web/index.html#/projections) you should see a projection name 'qry-person-stream'
- You should see something like this on the console:
- Run the CmdExampleApp to create a PersonCreatedEvent
- You should see something like this on the console:
INFO o.f.d.cmd.app.CmdExampleApp - Updated event store... - There should also be an update on the 'QryExampleApp' console:
INFO o.f.d.q.h.PersonCreatedEventHandler - Handle Person 'Peter Parker Inc.' was created - If you open the Event Store UI (User 'admin' / Password 'changeit') and open the projection details for 'qry-person-stream' it should show 'Events processed = 1'
- Look at the person's aggregate event stream: ```http://localhost:2113/web/index.html#/streams/PERSON-00000000-0000-0000-0000-000000000000`` - Replace the zero UUID with the one shown in the event handler message 'Person 'Peter Parker Inc.' (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) was created'
- You should see something like this on the console:
- Kill the QryExampleApp
- Stop the event store
What is in the application?
The application is splitted into three packages: 'shared', 'cmd' and 'qry'.
shared
Has code shared between both modules 'cmd' and 'qry'.
Sub package 'app'
There are several configuration classes used for CDI in the app package
cmd
Code for the 'command' or 'write' side of the application.
Sub package 'app'
Contains mainly the command line application.
- The command line application CmdExampleApp that creates a new Person aggregate and saves the state as a series of events in the EventStore (Event Sourcing).
Sub package 'domain'
There are three DDD domain model related classes
- The Person aggregate (Aggregate Root).
- The PersonRepository used to store the aggregate root in the event store.
Package 'qry'
Code for the 'query' or 'read' side of the application.
Overview
Sub package 'app'
There are several configuration classes used for CDI in the app package and the main query application.
- The command line application QryExampleApp that reads events from the EventStore (Event Sourcing) and updates it's internal view model.
- The QryTimer class fires an asynchronous CDI event called QryCheckForViewUpdatesEvent
Sub package 'domain'
The view data will be stored in an in-memory HSQL database using JPA
- The QryPerson class is an @javax.persistence.Entity class
- The QryPersonRepository class is used for the Apache DeltaSpike Data Module entity repository to simplifying the database access. (See EntityRepository)
Sub package 'handler'
The query side has to listen for new events. This is done by polling the Event Store every second.
- The QryProjector receives the event issued by the QryTimer and starts reading a from a projection that collects all necessary events required for one view.
- The QryEventChunkHandler is used to read all events of a single projection and dispatch them to the event handler that want to have them. It also updates the QryPersonProjectionPosition in the database. This is done to remember, what the last event was that was read from the event store's event stream (projection). It uses a helper class called SimpleEventDispatcher that is aware of all known events and capable to handle the 'dispatch' operation.
- The PersonCreatedEventHandler class is an example of an event handler that updates the local view database using a single event.
