Good day, I have a Spring Boot based backend , we are using own library to convert JPA entities to Dto's (library works based on reflection).
The problem is , we inject service layer directly to some mappers. Let's say I have a UserEntity
and UserDto
.
UserDto has a field called avatar and avatars are stored in S3
.
So in order to build a UserDto we are using the code like this.
@Component
class UserMapper {
@Inject
S3Service s3Service;
public UserDto toDto(UserEntity entity){
UserDto dto = new UserDto();
BeanUtils.copy(entity,dto);
dto.setAvatar(s3Service.getAvatarByUser(entity));
}
}
I don't like this approach because Mapper mustn't know anything about Service layer . However this mapper is used by other mappers as well. In case I want to return an OrderDto, it has a nested UserDto so OrderDto calls UserMapper internally. Are there any best practices for Mappers to be service free ?
So far I tried the following.
- Store avatar in
ThreadLocal
cache. When controller calls a service to get a user, service will store user's avatar in the ThreadLocal, and then Mapper will get it from ThreadLocal cache. Disadvantage - it's hard to test it and requires me to make Mocks - Create a separate POJO called UserWithAvatar that stores
UserEntity entity;String avatar
and create a mapper forUserWithAvatar
instead ofUserEntity
. Disadvantage - as I said this mapper will be used byOrderMapper
and order mapper takesOrderEntity
with nestedUserEntity
instead ofUserWithAvatar
I think mapper should be inside of service but I will try working with ur requirements
u have 2 choices:
You inject both service and mapper to controller, get entity back to the controller and map it using mapper before returning response
Use event publishing to publish an event which mapper then catches and produces the mapping. After that you could either directly return the dto to controller or produce another event. (event publishing is by default synchroneous so you dont have to worry about concurrency issues)
Event publishing is done via spring and results in very uncoupled code where publisher doesnt know anything about event subscribers and hence these 2 can be in 2 seperate layers that wont know anything about each other
Easy to follow guide: https://www.baeldung.com/spring-events