Profile Service
The Profile Service is a microservice that extends the domain data of the legacy Customer Service. This is the microservice that is strangling the domain data of the Customer Service—and in the process—slowly transitioning the system of record away from the large shared database in the legacy system. The Profile Service exposes protected domain resources as a REST API, using the Spring Cloud Security project to implement the OAuth2 client workflow.
1 |
|
In the code snippet above we see the ProfileControllerV1
class, which is a REST controller that provides an endpoint for retrieving the Profile
of a user. The Profile
object we are retrieving here will extend fields from the Customer
object, after retrieving domain data from the legacy Customer Service. To do this, we will call directly to the Customer Service in the legacy application zone using a SOAP client.
1 |
|
In the snippet above we find the definition of the CustomerClient
. This class will provide the Profile Service with a capable SOAP client that can retrieve a Customer
record from the legacy Customer Service
. We’ll use this client from the ProfileServiceV1
class below to retrieve the Customer
domain data that we will be extending in the Profile
object.
1 |
|
The code snippet above contains the definition of the ProfileServiceV1
class. This bean will conditionally call the legacy Customer Service by making a SOAP request from the CustomerClient
. The getProfile
method is called by the ProfileControllerV1
class, returning a Profile
object that extends domain data from the legacy Customer
object.
1 |
|
As a part of this workflow, the Profile Service looks to its attached MySQL database using the ProfileRepository
to find a Profile
record with username
as the lookup key. If the Profile
for the requested user does not exist in the database, a request to retrieve the Customer
object is made to the Customer Service. If the Customer Service returns a Customer
record in the response, the base domain data returned from the legacy Customer Service will be used to construct a new Profile
record, which is consequently saved by the Profile Service to the attached MySQL database.
Using this workflow, the Profile Service only needs to call the legacy system once for each Profile
that is requested. Since we’ve re-routed all requests from other legacy applications to use the Legacy Edge Service, we can safely transition the system of record for domain data away from the legacy Customer Service without performing any risky database migrations. Further, to support backward compatibility in the “large shared database”, we can replicate any updates to the base Customer
domain data by scheduling tasks asynchronously to call the Customer Service when a change is made to a Profile
.
1 |
|
The snippet above is the implementation of updateProfile
. In this method we are receiving a request to update the profile of a user. The first step is to ensure that the profile being modified is the user who is currently authenticated. To make sure that only a user that owns the profile can update the domain resource, we check to see if the requested change is different from the profile of the authenticated user.
|**|To support backward compatibility with the legacy system, we’ll need to support a different workflow for validating the authenticated user, since the Legacy Edge Service uses client_credentials
for authorization.|
After updating the profile, we need to replicate the write back to the customer service. To make sure that the cloud-native application is able to scale writes without dependency on the legacy system, we want to be able to durably replicate the write in an async workflow. By sending a durable message to a RabbitMQ queue, we can use the Profile Service to send back updates to the Customer Service asynchronously without tying up thread and memory resources of the web server.
1 |
|
The snippet above is our message listener on the Profile Service that will asynchronously issue writes back to the Customer Service in the legacy system. Since the network is prone to failure, this workflow ensures that there will be no loss of data since the RabbitMQ message can only be acknowledged after an attempt to update the Customer Service was a success.