Photo by Ben Sweet on Unsplash
Introduction
Each user that is registered with the application will be provisioned with an Account Profile which allows each user to maintain a both demographic information as well as the user's preferred avatar image. In this article, we will build the Account Profile Service to implement these features.Requirements
Before you get started, you will need the following:- Java
- Maven
- Docker
- Docker-Compose
Building the Account Profile Service
The AccountProfileService that we are implementing is a simple service. We will however, be introducing MongoDB for data persistence. Unlike the PostgreSQL database we used in the AuthenticationService, MongoDB is schema-less. This gives us the flexibility to evolve the account profile data model to meet the needs of an as-yet-unknown target application. There is no hard requirement that we use a schema-less database for persistence. We will, however, leave the relational implementation as an exercise for the reader.
In addition to providing a REST endpoint, the AccountProfileService provides an event queue message listener. This listener attaches to message bus to listen for AccountRegisteredEvent messages. When AccountRegisteredEvent messages are received, an Account Profile is created in the database.
The source
Maven pom.xml
loading...
Note that we include the spring-boot-starter-data-mongodb dependency which provides support for our MongoDB repository.
Configuration
bootstrap.yml
loading...
Not much different in this bootstrap file except for the spring.application.name
application.yml
loading...
There are three primary configurations of note here:
- spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS: false-This is set to false since we are using MongoDB.
- spring.data.mongodb-This section configures the MongoDB's connection information.
- spring.servlet.multipart-This section configures the min and max sizes for file uploading. This is needed to support avatar uploading in the AccountProfileImageController.
Repositories
The service contains two repositories; ProfileRepository and the ProfileImageRepository.Profile Repository
The ProfileRepository extends the MongoRepository and supplements the basic CRUD support with three query methods:loading...
- findByAccountId-query by account id.
- findByEmail-query by emaill address.
- findByQuery-This query searches the first name, middle name, last name, and email address fields for a match. If any of these fields contain the supplied value, it will be included in the Paged response.
Profile Image Repository
We will use the ProfileImageRepostory to store each profile's avatar in the MongoDB. It too, extends the MongoRepository and supplements the CRUD support with the lone findByAccountId method.loading...
Message Queue Listener
The QueueEventListener binds to the message queue through the ProfileQueueManager class. When messages arrive, their type headers are inspected and routed to the designated method.loading...
For incoming messages with a header type of Account_Registration_Event, the message will be routed to the processAccountRegisteredEvent. This method will create a new Profile instance and persist it to the database. All other messages will be routed to the trapUnmappedEvent.
Services
The ProfileService wraps both the ProfileRepository and the ProfileImageRepository, as well as the ProfileQueueManager, which are all @Autowired into the service.loading...
For create and update operations, the service generates corresponding events which are published back into the queue for downstream processing.
Controllers
The AccountProfileService contains two controllers; the AccountProfileController and the AccountProfileImageController.Account Profile Controller
loading...
This controller provide the REST endpoint for managing the Profile demographic data. It provides support for reading, updating and deleting Account Profiles.
Account Profile Image Controller
loading...
The AccountProfileImageController provides the endpoint to upload and download Account Profile avatar images.
Docker Compose
We continue the process of extending our Docker-Compose file by declaring the account-profile-service.loading...
Here we include the MongoDB service which will provide persistence service, and we include the Account Profile Service declaration.
Account Profile 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-09-account-profile.yml up -d
Exercising the Swagger Interface
When all the services have started, navigate to the following url: http://localhost:5020/swagger-ui.htmlIn this service, all of the endpoint methods require authorization. To generate a JSON Web Token (JWT) we have two options. The first option it to navigate to the AuthenticationService's Swagger interface ( http://localhost:7777/swagger-ui.html), select the /authenticate option.
Populate the credentials in the request JSON, and click the Execute button.
The response body will include the JWT we need to supply to our AccountProfileService authorization header. While this is certainly a valid approach for generating neccesary authentication tokens, it can be time consuming.
The second approach is to use curl to invoke the AuthenticationService endpoint from a command prompt.
curl -X POST "http://localhost:7777/authenticate" -H "accept: */*" -H "Content-Type: application/json" -d "{ \"email\": \"admin@thinkmicroservices.com\", \"password\": \"Password_1\"}"
This will yield:
{"success":true,"token":"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbkB0aGlua21pY3Jvc2VydmljZXMuY29tIiwiYWNjb3VudElEIjoiMGNkOGNlODUtZmFmMC00M2M2LWE4MjQtMmZkYWE3MzM1YzAzIiwicmVmcmVzaF90b2tlbiI6ImQ0ZjhjNzgzLTFjZWYtNDBmOC1iMWM3LTBhMDBhYjZiMjUxYyIsInJvbGVzIjpbImFkbWluIiwidXNlciJdLCJpc3MiOiJUaGlua01pY3Jvc2VydmljZXMuY29tIiwiZXhwIjoxNTg1NzAzMzQyLCJpYXQiOjE1ODU3MDMyODIsInJlZnJlc2hfdG9rZW5fZXhwIjoxNTg1NzA0MTgyNjc3fQ.G_z2cO-C5y1xOoOPhGWHe2N1kRuTmOxfd793HDpIiB6PkC_h_tA0-1-_Q2v4liStp2_GgbHNo-dwiwZS7IOO-A","errorMessage":null}
(
NOTE: The value of the token will be different )
This approach can be faster, especially if run from a simple shell script. When exercising secured REST interfaces, we will need a source of valid, non-expired authentication token.
We will exercise the Swagger UI by seleting the /profile/all option. This method will return a paged listing of all profiles that match the like field regex value.
We will use the default values for every field except the Authorization. In this field we supply the authorization token we received and we prefix it with the bearer string and a single space. When we click the Execute button, we will see the following.
Here we see a partial response displayed in the Swagger UI. The full JSON response is:
{
"content": [
{
"id": "5e83c5a3048be40001b4c73c",
"accountId": "0cd8ce85-faf0-43c6-a824-2fdaa7335c03",
"email": "admin@thinkmicroservices.com",
"firstName": "Admin",
"lastName": "Strator",
"middleName": "I",
"primaryStreetAddress": null,
"secondaryStreetAddress": null,
"city": null,
"state": null,
"postalCode": null,
"phone": null,
"dob": null
}
],
"pageable": {
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"pageSize": 10,
"pageNumber": 0,
"offset": 0,
"unpaged": false,
"paged": true
},
"totalPages": 1,
"totalElements": 1,
"last": true,
"numberOfElements": 1,
"sort": {
"sorted": true,
"unsorted": false,
"empty": false
},
"first": true,
"size": 10,
"number": 0,
"empty": false
}
The
JSON response is in the form:
Here we see that the paged response has a single profile. To edit this profile we return to the top-level options and select the PUT /profile/account/{id}option. To exercise this option click the Try it out button.
Here we supply a valid Authorization token, the id if the profile we want to update, and we supply the request JSON with the primary street address, city, state, and postal code field values reflecting the changes we wish to make.
We can verify that our updates by returning to the top-level options and select the GET /profile/account/{id} option.
We supply a valid authentication token, the account id, and click Execute.
The JSON response confirms that our changes have been persisted.
Metrics and Monitoring
The Account Profiles Service generates the following service-level metrics:- account.profile.created.total
- account.profile.updated.total
- account.profile.deleted.total
To visualize this data we will import the AccountProfilesDashboard.json file from the ThinkMicroservices Github Dashboards repository. The dashboard should appear as:
Resources
- AccountProfileService Github repository
- AccountProfileService Docker hub image.
- ThinkMicroservice AccountProfileService Dashboard.
Twitter
Facebook
Reddit
LinkedIn
Email