6

If i have the below entities in tow separate microservices :

class Employee {
@Id
private Long employeeId;

private String name;
...
}

class Department {
@Id
private Long deptId;

private String name;
...
}

How can i add a many to many relation between the entities ?

I thought of combine the two entities in one entity on the gateway :

class Empl_Dept{
List<Long> employeeIds;
List<Long> departmentIds;
}

so the junction table will be on the gateway side.

Is there any better solution??

3 Answers3

13

Assuming you have your domains modeled properly, this seems like an easy fix with Integration Events.

Add an EmployeeIds table to your Departments Service and a DepartmentIds table to your Employees service. When you make, break, or change an assignment between an Employee and a Department, publish a EmployeeDepartmentUpdated event that both services subscribe to. Then, each service can process the event and update their own data to keep in sync.

You do NOT want to start putting data into your gateway API, that's not what it's for (and it means that if you have multiple gateways to the same back-end services, only one will know that information).

Embrace Eventual Consistency and your microservices journey will be the better for it!

EDIT:

To your question about the impact of Events on performance and complexity, the answers are "no" and "yes."

First, no I would not expect event-sourcing to have a negative impact on system performance. In fact, their asynchronous nature makes event processing a separate concern from API responsiveness.

I'm sure there are ways to build a Service Oriented Architecture (SOA, of which microservices is essentially a subset) without a messaging plane, but in my experience having one is a fantastic way to let loosely-coupled communication happen.

Any direct calls between services - regardless of protocol (HTTP, gRPC, etc.) means tight coupling between those services. Endpoint names, arguments, etc. are all opportunities for breaking changes. When you use messaging, each service is responsible for emitting backward-compatible events and every other service can choose which events it cares about, subscribe to them, and never have any knowledge of whether the emitting service is running, dead, changed, etc.

To your second question, the answer is absolutely "yes" - event processing is additional complexity. However, it's part of the complexity you sign up for (and far from the worst of it) when you choose a microservices architecture style. Distributed authorization, keeping UI performant with multiple back-end calls organized between multiple services, fault tolerance and health/performance monitoring are all (at least in my experience) bigger challenges.

For the record, we use a hosted instance of RabbitMQ from CloudAMQP.com and it works great. Performance is good, they have lots of scalable packages to choose from, and we've had zero issues with performance or downtime. The latest RabbitMQ 3.8 release now includes OAuth as well so we are currently working to integrate our Authz flows with our message broker and will have a nice end-to-end security solution.

meshtron
  • 1,110
  • 9
  • 19
  • Yes, i have seen blogs talking about such events. Don't you think that events will be costy in terms of performance ? And they might add complexity to the system? – Mohammad Makahleh Oct 23 '19 at 14:21
  • I added more to my answer to address your questions. – meshtron Oct 23 '19 at 15:58
  • Many thanks. Don't you think that i can easily add the junction table in one side (which is the side that will write on it) and the other side can request info by sending the ids. Although it would be a confusing since the junction table is not par t of any service.. it is a relation between them. – Mohammad Makahleh Oct 24 '19 at 13:45
  • You could add it to one or the other, but since the relationship is between the two entities, it is better form to add it to both. Again, if you added it to (say) the Employees Service only and made Departments Service call that service directly any time it needed the information, you've created a tight coupling between those services that causes a problem in the Employee Service to bleed over into the Department Service. – meshtron Oct 24 '19 at 14:02
  • You are welcome. If you believe this has fully answered your question, please click the checkmark to "Accept" the answer. If not, let me know what other questions you have. – meshtron Oct 24 '19 at 14:53
1

Each microservice sould have it own database, so the junction table has no sense because it's a relational solution.

You may consideer one of this two approaches, if the Empl_Dept is a Domain object you should put it in a third microsevice, if it isn't put the employees relation into department and vice-versa.

I hope it helps.

0
  1. I am assuming, This many to many map is required in a third microservice. Then It's straightforward you create a map table between employee and department
  2. If you have only those 2 microservices then you will have to add employee_department_map in one service and department_employee_map in second service.

While designing a microservice always consider that you can't change anything in another service (let's say if it's third party api)

Abhishek Ranjan
  • 157
  • 2
  • 7
  • Don't you think that i can easily add the junction table in one side (which is the side that will write on it) and the other side can request info by sending the ids. Although it would be a confusing since the junction table is not par t of any service.. it is a relation between them. – Mohammad Makahleh Oct 24 '19 at 13:44
  • Depends if junction table is consumed in both the services. Where data from this many to many is consumed you need to have mapping table innall those services – Abhishek Ranjan Oct 24 '19 at 13:50