Best way to design microservice architecture when there is a dependency between databases? - spring-boot

We are planning to migrate our product to micro service architecture using spring boot.
I have few doubts/concerns for "each service should have separate database".
If I created separate database for each service, then how to handle the table dependency.
For example: I have 2 micro services.
1. Customer Service: it has "customer" table (fields: customerId, customerName, etc...)
2. Order Service: it has "order" table (fields: orderId, orderName, customerId, etc...)
Note: for simplicity I mentioned only 1 table in each service here.
When I tried to access the order details based on orderId, I may want to retrieve the details of customer also.
In this case, I have two options in my mind:
Using RestTemplate call the "customer service" GET of customerById API and fetch the required details and set it in the response of OrderDetails.
Create customer table also in Order Service and using database tool replicate the data from customer service to order service's customer table. i.e., any changes done to customer table in customer service database will reflect on order service's customer table.
So, I can easily fetch relevant data from order service itself.
Please suggest which one is preferable. If both doesn't make sense, please suggest best way to handle this.
Thanks.

Related

Fetching the employee tasks list from SAP ByD via OData API

In SAP Business ByDesign (SAP ByD), a project can have multiple tasks and each task can have assigned multiple employees. So a single user has a list of tasks to book time on.
In the SAP ByD UI, you can select an employee and see all the assigned tasks. I would like to fetch that via the OData API. I started to click together some OData Services.
I have an Endpoint that allows me to filter for an employee:
https://my1234567.sapbydesign.com/sap/byd/odata/cust/v1/employees/EmployeeCollection?$format=json&$filter=EmployeeID eq '1234567'
With that, I can fetch information about an employee.
And I have an Endpoint to fetch ProjectTasks:
https://my1234567.sapbydesign.com/sap/byd/odata/cust/v1/project/ProjectTaskCollection?$format=json
That collection contains always a reference to the project.
And I have a ProjectParticipant collection that tells me which user is a member of which project:
https://my1234567.sapbydesign.com/sap/byd/odata/cust/v1/project/ProjectParticipantCollection?$format=json
And I can filter that ProjectParticipant collection by employee ID. With that I know which projects a user has assigned. But that does not tell me which exact tasks the user has assigned in the project. This last piece of the puzzle is missing.
I'm very new to SAP. If somebody can give me a hint for the right data model or API, I would be very thankful.

Defining Microservice boundaries

I have started learning and building micro service based project, but I always stuck into scoping situation and end up creating a sort of monolith. in my below foo-bar example, please suggest what should be the scoping and how achieve desired output.
Services or tables
Employees
Department
Employee-Department-Mapping
Assumption
Employee or Department does not have any cross reference for each other all relationships are maintained in 3rd table Employee-Department-Mapping
Relationship could be One-To-Many or Many-To-Many based on business to business, in this example it is One-To-Many (Department with Employee)
Requirement
I want to get total salaries paid department wise. similar to below query, here I am making simple joins on 3 tables. which is only possible if all are in the same database and single micro service.
Select d.DepartmentName, SUM(e.salary)
from Employee e, Department d, Employee-Department-Mapping c
where d.DepartmentName == c.DepartmentName
AND e.Employee == c.Employee
Group By c.DepatmentId
constraints
employee table has salary information
employee department relationship is maintained by 3rd table.
I am not looking for exact answer but an approach to solve such problems.
wonder how would you design your micro service if you need aggregated outputs, would you bring all these tables in the single microservice ? I do not want pull millions of records from everymicroservice and do aggregation in memory.
Microservice boundries -if you don't have any other scalability reason- should be defined by the business. And in this particular case -without knowing any other requirements- I would say you should go for one microservice which manage those 2 entities. Having said that I experienced enough to know that in the real world this solution is not always feasible and possible. Fortunately there are some patterns you can follow to fix the situation you described. For example CQRS could be a solution https://dzone.com/articles/microservices-with-cqrs-and-event-sourcing.
You have to change your thinking to microservices here. what I can propose here is
You will have to do multiple calls to different microservices and return one result you can use API Gateway pattern. You will have to write an aggregator service to aggregate the output of the two tables via two API services.
You will have to denormalize the database and have the dept name in your Employees table if you don't like the above option. That's why we use NoSQL in microservices.

Microservice and service collaboration

In the context of a Microservice architecture, a single business operation can require collaboration between two or more services.
Suppose we have an Order Management Service and a Product Catalog Service.
When the user adds an order item to an order, the Order Management Service will persist a OrderItem object which have the following attributes among many others :
OrderItem
+ Id
+ ProductId
+ ProductName
In order for the Order Management Service to fill the ProductName attribute, we have 4 choices as I see it :
Choice 1 : ProductName is given by the client app as it probably already has this data from previous requests
Choice 2 : If the architecture uses an Api Gateway, the gateway will be responsible for retrieving the ProductName from the Product Catalog Service then provide it to the Order Management Service.
Choice 3 : The Order Management Service will call directly the Product Catalog Service and asks him for the ProductName givent a product id.
Choice 4 : The Order Management Service has a duplicate (but not exhaustive) product informations in its own database and these datas will be updated each time an update event is received from the Product Catalog Service.
Among these 4 choices, the n°1 seems not ok to me as we can't trust the client to give us a correct and updated value of ProductName.
I would like to have your opinion about what you think the best choice is and why !
Thanks !
Riana
Choice 1 : ProductName is given by the client app as it probably already has this data from previous requests
Like you said, it is not the best idea because the client may have stale information. Maybe acceptable if the product information changes infrequently and/or you have a secondary verification at order processing.
Choice 2 : If the architecture uses an Api Gateway, the gateway will be responsible for retrieving the ProductName from the Product Catalog Service then provide it to the Order Management Service.
IMHO, this is not a good idea. By doing so your domain/business logic will leak into the API Gateway. The gateway now knows the relationship between Orders and Products. This API gateway configuration/scripting will need to be maintained and introduces additional coupling.
Choice 3 : The Order Management Service will call directly the Product Catalog Service and asks him for the ProductName givent a product id.
This is my preferred choice. Though I do not recommend "direct" synchronous calls. Perhaps a retrieval of the ProductName via a messaging mechanism (message queue, event bus). Chained synchronous calls will reduce the availability of your services. You can find more information at Microservice Messaging Pattern.
Choice 4 : The Order Management Service has a duplicate (but not exhaustive) product informations in its own database and these datas will be updated each time an update event is received from the Product Catalog Service.
Data duplication is generally frowned upon unless there is a really good reason for it. In this case I don't see any. Why bother splitting the databases into two for each of the services yet duplicate the data between them? Also, to have the data updated each time an update event is received indicates that some kind of event/messaging infrastructure is available, in that case, why not just use messaging?
This duplication may be justifiable for high volume, low latency look ups, but it is a slippery slope that may end up with duplicated data all over your services. Imagine the repercussions of a length or type/format change of the ProductName string...

Use DB Relationships in spring boot micro services

I want to use the many to one and other DB Relationship in micro-service architecture. In monolithic architecture we can create the entity relationship easily as they belongs to same project but in micro-service architecture how we can achieve the same.
Example:
There is one userDeatil service and other is productDetail service.Now there is third service called orderDetail and an order will have userID and ProductIDs associated with it. So how can we manage the relationship between 'user and order' and 'order and product'.
I have searched over net but didn't able to get the fair idea.There is another thread having same query but not having the clear answer. Link
In my opinion your case is about how you specify your services especially how you define the bounded context of each service !!
According to the situation above-mentioned I don't see any reason why the product service should know anythings about orders (even if it s just the order-id) and backwards. One more problem I see in this case: your services will not work if one service is not available (E.g when the product service it not online, your order service will not be able to work, because he needs the product details from the product service...).
I Think you should rethink the bounded contexts of your microservices. You should keep in mind:
ensure a loose coupling of the microservices
a microservice has always to work even other Microservices are not available (Resilience / Reliability).
The DDD (domain-driven-design) paradigm with its tools provides her a great help to assist you, during the definition process of your services, you encourage these qualities.
So, the following is JUST an idea (it s not a recommendation and you should review whether it matters for your business case) :
It seems like the "order" process is your core business domain. So you have to focus on it.
The user service (i hope you mean here the customer and not a user in terms of authentication/authorization) has only the responsibility to manage the customers, and may be their adresses, bank-Accountings etc.. It should not know anything about your orders or products.
The same is valid for the product service. It owns only data about products. It has no relation either to the customer nor to the order-service.
The order service by itself deals only with orders and should own only data that belong to an order (like ship Adress and some information about the product-items ordered). I think the customer-Id is also important here to keep the relation between the order and the customer. This way you can e.g get all orders made by a certain customer-id....

Coupling in microservices architecture

When working on an application in microservices architecture I stumbled upon issues concerning coupling between services.
This a typical application for ordering products. It seams reasonable to have a service that will operate as a product catalog. Our JavaScript client can ask this service for available products and show them in browser. When user clicks on a product we have to create an order. We would like to manage orders in another service. So an order is created - it means that user X ordered product Y. On the technical level we are simply persisting user id and product id in a database.
To sum up we have:
Products service
Product class:
Product ID, Product Name
Orders service
Order class:
Order ID, Product ID, User ID, Order date
Now let's imagine following scenario - in JavaScript client we would like to list all products that user have ordered. Orders service provides a list of products ids for a given user. But user cares about product name, not the id. Unfortunately Orders service doesn't know anything about products names.
We could tackle this in couple of ways:
Simply assume that the client is responsible for getting the information it needs. So after it calls Orders service and gets a list of products ids, it performs another call to Products service, passing products ids and getting corresponding products names in response. Then the client assembles both responses into something useful. This approach keeps our services clean, without leaking of domain knowledge from one service to another. But it requires more work on the client side.
Orders service when asked for ordered products makes a call on the backend to the Products service. It retrieves product names, assembles a response that contains orderDate and productName and sends that to client. All that's left for client to do is to present the data. Downside of this approach is that Orders service now gains more knowledge about products than neccessary.
Duplicate information about product name in Orders service. When an order is created, we pass not only product id but also product name. That means that Order class will look like this:
Order class:
Order ID, Product ID, Product name, User ID, Order date
Now we can easly provide full information about order without additional call to Products service. Also this time Orders service has too much knowledge about products. What's beneficial tough is that Orders service can provide relevant data even if Products service is down.
Could any of these approaches be considered best practice? Or are there different solutions?
In the eShopOnContainers example( https://github.com/dotnet-architecture/eShopOnContainers ), they add the following fields at the time an order item is created:
public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1)
This duplicates the catalog information, however as this is a point in time snapshot of the record. This is far safer than linking to the original data.
At this point in the user journey you are in the domain of an order, if a user is viewing an order you can provide a link to the catalogue. However, the order service should be able to operate independently. Linking back to the catalogue for the information on products prevents the Order service owning it's own data.
A nightmare scenario being that a price changes in the catalogue... What would happen to the historic orders?

Resources