Search code examples
spring-bootdesign-patternsdomain-driven-designhexagonal-architecture

Dependency between adapters in hexagonal architecture Spring Boot


I've been trying to refactor a brand new project to follow the hexagonal architecture and ddd patterns.

Domain structure

This is the structure of my domain. I have files and customer data. Entity wise this makes sense to be separated. The "facade" objects connect the ports with the domain. Quick example:

Controller (application layer) --uses--> Facade --uses--> Ports <--implement-- Adapters (infrastructure layer)

The problem I have is I have a third adapter (not in the picture) that is an external OCR app. It's an external client (we use a feign client to connect their API) and it provides customer data (first adapter), but also serves us with the raw data of images (second adapter).

My first two adapters have entities, repos and databases on our local systems but, this third one, to me makes sense given the theory behind hexagonal architecture, to be separated in its own adapter.

But then how do I use it from my other two adapters? Should the three of them be in the same adapter since they depend on each other? CustomerData and File have a One To Many relationship as well so maybe it makes sense?

I have only implemented the File part so far and have yet to refactor the CustomerData part since I'm trying to wrap my head around the concepts first.

I've seen a lot of articles but most of them are really simple with no real world examples and they have clearly separated domains.

Thanks a lot for the clarification in advance.


Solution

  • In lack of a better idea, since the interface ports are beans implemented by the facades, I'm wiring the ports I need in the other domain's facades and using them the same way as if it was a controller of that same domain. The diagram would be something similar to:

    Facade (domain1) --uses--> Port (of domain2) <--implement-- Adapters (infrastructure layer)

    Edit:

    I've found out a very extensive article that is very useful to understand hexagonal architecture but goes even deeper.

    Long story short, I'll copy the relevant part:

    Triggering logic in other components

    When one of our components (component B) needs to do something whenever something else happens in another component (component A), we can not simply make a direct call from component A to a class/method in component B because A would then be coupled to B.

    However we can make A use an event dispatcher to dispatch an application event that will be delivered to any component listening to it, including B, and the event listener in B will trigger the desired action. This means that component A will depend on an event dispatcher, but it will be decoupled from B.