Photo by Vashishtha Jogi on Unsplash
Introduction
During the application's operation, various account-related events will be created and published to the application message bus. We want to capture these events and persist them for auditing and analysis purposes. In this article, we build the Account History Service, which provides a historical log for each account-related operation performed by the application. The service binds to the message broker and receives all account-related events published, and persists these events to a MongoDB database. Additionally, a REST interface provides an endpoint to provide query facilities.Requirements
Before you get started, you will need the following:- SDKMan
- Java
- Maven
- Docker
- Docker-Compose
Building the Account History Service
The AccountHistoryService that we are implementing is a simple service. The bulk of the service is composed of a QueueListener and the various event repositories. We will be persisting events to MongoDB using the same rationale we had for the AccountProfileService, flexibility. This approach gives the reference implementation the flexibility to evolve the account history data model to meet an as-yet-unknown target application's needs.
Account Events
The AccountHistoryService currently listens for the following events:Event Type | Event Source |
---|---|
AccountRegisteredEvent | AuthenticationService |
CredentialsAuthenticationRequestedEvent | AuthenticationService |
PasswordChangedEvent | AuthenticationService |
PasswordRecoveryRequestedEvent | AuthenticationService |
PasswordRecoveryCompletedEvent | AuthenticationService |
AccountStatusChangedEvent | AuthenticationService |
ProfileCreatedEvent | AccountProfileService |
ProfileUpdatedEvent | AccountProfileService |
ProfileDeletedEvent | AccountProfileService |
ProfileImageCreatedEvent | AccountProfileService |
ProfileImageUpdatedEvent | AccountProfileService |
ProfileImageDeletedEvent | AccountProfileService |
The source
Maven pom.xml
loading...
bootstrap.yml
loading...
Not much different in this bootstrap file except for the spring.application.name
application.yml
loading...
Queue Event Listener
All events persisted in the Account History Service originate as events delivered to the service via the QueueEventListener. This listener binds to the message queue's AccountEvents input destination defined in the application.yml configuration file. This binding is configured with the input group accountHistoryGroup to allow multiple instances of the Account History Service to be deployed while ensuring that the event message will only be delivered to a single instance for processing.loading...
As event messages arrive, they are routed to the appropriate handler method based on the contents of the message's headers['type'] value. We add the @StreamListener annotation to each message handler method and include the condition value expression to match the headers['type'] value. Each handler method then persists the event to the corresponding repository and updates the relevant custom service metrics. As the application evolves and new use cases require additional event types, we can add new @StreamListener methods to the QueueEventListener and configure the condition expression accordingly.
Polymorphic Event Repository
Our goal is to persist each of these events in a single MongoDB Collection. To accomplish this, we will be building a PolymorphicEventRepository. This approach allows us to map multiple event repositories to the same collection, and then query the collection to return events objects of differing types. By aggregating different event types within the same collection, we can simplify our query mechanism and avoid the need to make (n) queries across (m) unique event collections. To accomplish this, we create a repository interface for each corresponding event type. We use this interface to add events, and to perform queries exclusive to this specific event type. However, we query the repository interface for the base event class when we wish to query across all event types. This approach gives us the best of both worlds.Event Repository
We start by creating a repository for the base event type AccountEventloading...
Now we simply create a repository interface for each of the event types that we wish to persist...
Account Registered Repository
loading...
Profile Created Repository
loading...
Credential Authentication Request Repository
loading...
Password Changed Repository
loading...
Password Recovery Requested Repository
loading...
As the application evolves, we simple define a new repository interface and add it to the service.
Account History Controller
Now that we have a mechanism that populates our account history, we need a way to access this data. To accomplish this, we create the AccountHistoryController.loading...
The controller exposes three methods:
- getPagedHistory- returns a paged list of all events.
- find- takes an instance of PagedEventHistoryRequest containing the query parameters, and returns a Paged set of results.
- getEventTypes- returns the set of Account History event types that have been persisted.
Docker Compose
We continue the process of extending our Docker-Compose file by adding our account-history-service.loading...
Account History Service In Action
We can copy the Docker-Compose file above to your local machine and run it from the command prompt:docker-compose -f ./dc-10-account-history.yml up -d
Exercising the Swagger Interface
When all the services have started, navigate to the following url: http://localhost:5010/swagger-ui.htmlHere we see three endpoint methods and the service data models.
Get Paged History
If we expand the GET /all we can see the method form.Clicking on the Try it out button will make the form interactive, and we can supply values to each parameter. Click the Execute button to view the paged results.
Changing the pageNo value, allows us to page through the results.
Get Event Types
Expanding the GET /eventTypes we can view the method form.Clicking on the Try it out button and supply values to each parameter. Then click the Execute button to view the results.
The service returns an array containing only the event types that have been received. If the application hasn't been exercised completely, some event types may not appear.
Find
Expanding the POST /find we can view the method form.Click the Tryit out button and can supply values to each parameter. Then click the Execute button to view the paged results.
The result contains paged results for the query parameters supplied.
Metrics and Monitoring
The Account History Service generates the following service-level metrics:- account.history.registration.event.total
- account.history.authentication.event.total
- account.history.password.change.event.total
- account.history.profile.created.event.total
- account.history.password.recovery.request.event.total
- account.history.password.recovery.completed.event.total
To visualize this data we will import the AccountHistoryDashboard.json file from the ThinkMicroservices Github Dashboards repository. The dashboard should appear as:
Resources
- AccountHistoryService Github repository
- AccountHistoryService Docker hub image.
- ThinkMicroservice AccountHistoryService Dashboard
Twitter
Facebook
Reddit
LinkedIn
Email