I'm going to start a new project to learn spring boot, spring data, and the hexagonal architecture. From my understanding the hexagonal architecture aims to separate the core or domain layer from the database operations (Infrastructure Layer). I have seen the following project structure for this architecture.
The Core Layer has:
Services-> Where the logic goes (interfaces and their implementations).
Entities -> These are going to be used in the entire application.
Repository-> Interfaces that the infrastructure layer has to implement.
The Infrastructure Layer has the implementation of the Repository interfaces, the JPA entities, calls made to the database (hibernate) and some sort of functions to transform the JPA entities to the Core Entities (mappers?).
Spring data has a very useful way to implement CRUD operations:
public interface UserRepository extends JpaRepository<User, Integer> {
}
However, I think if I use spring data, the JPA entities won't be part of the Infrastructure Layer if UserRepository is part of the Core Layer. This means that the Core entities would be useless. Should I create another UserRepository interface that belong to the Core Layer or Is there something I am missing?
UPDATE:
My concern using spring data comes from that I have to include the JPA entities inside the domain, which In theory would violate the hexagonal architecture.
So I was thinking to separate the domain Entities from the JPA entities. but If I do this I don't know where the repository of Spring Data should go and also find a way to transform the JPA entities into the Domain entities.
To ilustrate a little bit better I'm going to assume that I need to connect to a database from my application to read a users table.
This could be Domain Entity:
public class UserDomain{
private String name;
....//More fields, getters, and setters.
From my understanding, the services should include the logic and operates the Domain entities.
public interface UserService{
public void create(UserDomain user);
...
The implementation:
public class UserServiceImpl implements UserService{
public void create(UserDomain user) {
... //Calling the repository(Spring Data Repository?)
The above along with the repository interface is what I consider the Domain (If I'm wrong please correct me). Next, the infrastructure is composed by the JPA entities
@Entity
@Table(name="users")
public class User{
@Column(name="name")
private String name;
... // More Fields, getters, and setters
I think the interface in which I call Spring Data should be in the infrastructure part because later I need to map the JPA entities into the Domain entities and maybe I need to use yet another class (and adapter?) to do that mapping. Is this approach correct or Is there any other way? Sorry for the long post,I hope I have made myself clear.
Hexagonal architecture, or port and adapter architecture, is an architectural pattern used in software design.
Hexagonal architecture is applied to one microservice. And if you are using DDD: At strategic level, each microservice would be a bounded context. At tactic level, inside each microservice, the hexagon would enclose the application layer and the domain model.
In the book, DDD examples use a traditional layered architecture, but the book also states that DDD can be used along with any other software architecture. If you want to use hexagonal architecture it's fine too.
Hexagonal architecture is a term coined by Alistair Cockburn in 2006. The other name of Hexagonal architecture is Ports And Adapters architecture. This architecture divides an application into two parts namely, the inside part and the outside part. The core logic of an application is considered as the inside part.
Here is a good article on how to connect your database to your application: http://www.dossier-andreas.net/software_architecture/ports_and_adapters.html
What you are trying to do is creating a 'secondary port' and 'secondary adapter'.
The 'secondary port' (= interface) describes what to do, but has no framework dependencies. The 'secondary adapter' (= implementation) uses the jpa-repositories.
A jpa-entity cannot be your domain. It describes how the data is stored in the database. So a jpa-entity cannot be used in the 'secondary port', only your domain.
The 'secondary adapter' will need to convert your domain to jpa-entities.
Be careful, though, if you really want to use the proper hexagonal architecture. The power of Hibernate, and later JPA, was that the jpa-entity is your domain. It makes things a lot simpler (and harder). By splitting your domain from your entities, you'll loose lazy-loading opportunities, clear transaction boundaries, orphan deletion, ... Maybe you should make a trade-of and putting jpa within the core-layer.
I hope you've found this helpfull
I'm a little confused about your question. You talk a lot about layers, while what I consider "the article" about hexagonal architecture uses that term (almost ?) exclusively for describing what not to do.
Spring Data fits nicely with the hexagonal approach: Entities form your core domain, repository interfaces form the database facing API. Note that the implementation (outside the core domain, mostly provided by Spring Data itself) depends on the interface, not the other way round). Services and/or Controler form one or more user-facing APIs.
There are some violations of the rules prescribed by the hexagonal architecture: The annotations on the entities and also on repositories. They are inside the core domain but depend on the usage/implementation of the database access by being part of JPA or Spring Data.
JPA itself violates the hexagonal architecture even further in that the behavior fo the persistence implementation might leak heavily into your domain because if you work with managed entities any change gets automatically tracked and eventually persisted without any call to the persistence API. Also, changes to the persistence layer like the configuration of the flush strategy might completely change the behavior of your API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With