Multiple Hexagonal architecture with sprint boot

291 views Asked by At

I work on a spring boot application with spring data and hibernate. I am using hexagonal architecture. I have 2 hexagons:

  1. ConnexionManagment
  2. OrderManagment

Each hexagon interacts with the same table in the database called User. In the OrderManagment hexagon I use User table because user have a list of orders And in ConnexionManagment hexagon I use User table because I need to manage user information when the user subscribes and other things.

So in each hexagon U have added the same UserjpaEntity to interact with table user in the infrastructure layer.

Is it good practice to duplicate class userJpaEntity in each hexagon? Or do I have to create a common hexagon and put all common classes in this hexagon?

To finish we can imagine other hexagon separate by functional domain which need to interact with the same table user in database.

So can you help me to find the best practice? enter image description here Thanks.

2

There are 2 answers

0
René Link On

Is it good practice to duplicate class userJpaEntity in each hexagon?

Do both contexts access the same properties or do you access different parts of the userJpaEntity from the ConnexionManagment and the OrderManagment? In other words do you load more things from the database in each context then they need? If so, it is not the same userJpaEntity that you need.

Even if the userJpaEntity looks the same in both contexts. Does the userJpaEntity change for the same reasons? If not it should be separated to honor the single responsibility principle, even if it look the same. It often only looks the same by accident.

Or do I have to create a common hexagon and put all common classes in this hexagon?

You might want to use a shared kerned. I mean that you have a common domain entity that the userJpaEntity is mapped to. Having a shared kernel might also mean that you have a shared "infrastructure", like the userJpaEntity, that is used to load the domain entity. You can then put the userJpaEntity in a separate module (library) that is used by the secondary port implementers, the adapters. I would not call this a common hexagon. It's just a shared kernel and some other shared librarie. Just parts of a hexagon that are shared.

Whenever you use one thing from different contexts you create a dependency between them. Thus, you have to make changes in all contexts when the thing that all use changes. It might be ok.

0
джедай On

hexagonal architecture seems like this

  1. repository-adapter
  2. rest-adapter
  3. another-external-adapter
  4. domain

repository module should have all processes to work with database, for example: UserJpaRepository, OrderJpaRepository

and you should create ports to interact with repository module in another modules, for example in domain module you will create interfaces(ports) to interact with other modules, and in repository-adapter module you should implement this interface and provide bean for spring (like annotating with @Repository)

domain

package org.example.domain.repository

public interface UserRepository {
    //write your methods here
    void saveExample(final DtoAsEntity e);
}

repository-adapter

package org.example.repositoryadapter.repository

@Repository
public interface UserJpaRepository extends JpaRepository<Entiry, ID> {
}

domain service implementation (port)

package org.example.repositoryadapter.adapter

@Component
public class UserRepositoryImpl implements UserRepository {
    @Autowired
    private final UserJpaRepository userJpaRepository;
    @Autowired
    private final ModelMapper mapper;

    @Override
    public void save(final DtoAsEntity dtoAsEntity) {
    userJpaRepository.save(mapper.map(dtoAsEntity, YourEntity.class));
    }
}

also you should remember, that hexagons should interact each other with some dto's, and remember also that you call domain module which mean maven dependency should be added in repository-adapter module

<dependency>
        <groupId>org.example</groupId>
        <artifactId>domain</artifactId>
        <version>1.0-SNAPSHOT</version>
</dependency>