0

I have a spring-boot application and I use DTO like that: Service

@Service
public class UnitOfMeasureServiceImpl implements IUnitOfMeasureService {
private final IUnitsOfMeasureRepository unitOfMeasureRepository;

@Autowired
public UnitOfMeasureServiceImpl(IUnitsOfMeasureRepository unitOfMeasureRepository) {
    this.unitOfMeasureRepository = unitOfMeasureRepository;
}

@Override
public UnitOfMeasureDTO getUnitOfMeasureById(UUID id) {
    Optional<UnitOfMeasure> optionalUnitOfMeasure = unitOfMeasureRepository.findById(id);

    if (!optionalUnitOfMeasure.isPresent()){
        // throw new ComponentNotFoundException(id);
        return null;
    }
    return UnitOfMeasureDTO.factory(optionalUnitOfMeasure.get());

}

dto:

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UnitOfMeasureDTO {

    private String id;

    private String name;

    private String description;

    private String sourceInfoCompanyName;

    private String originalId;

    public static UnitOfMeasureDTO factory(UnitOfMeasure unitOfMeasure) {
            UnitOfMeasureDTO dto = new UnitOfMeasureDTO();

            dto.id = unitOfMeasure.getId().toString();
            dto.name = unitOfMeasure.getName();
            dto.description = unitOfMeasure.getDescription();
            dto.sourceInfoCompanyName = unitOfMeasure.getSourceInfo().getSourceCompany().getName();
            dto.originalId = unitOfMeasure.getOriginalId();
            return dto;
    }

  }

controller:

@RestController
@RequestMapping(UnitOfMeasureController.BASE_URL)
public class UnitOfMeasureController {

public static final String BASE_URL = "/api/sust/v1/unitOfMeasures";

private final IUnitOfMeasureService unitOfMeasureService;

public UnitOfMeasureController(IUnitOfMeasureService unitOfMeasureService) {
    this.unitOfMeasureService = unitOfMeasureService;
}

@GetMapping(path = "/{id}")
@ResponseStatus(HttpStatus.OK)
public UnitOfMeasureDTO getUnitOfMeasureDTO(@PathVariable("id")  UUID id) {

    UnitOfMeasureDTO unitOfMeasureDTO = unitOfMeasureService.getUnitOfMeasureById(id);

    return unitOfMeasureDTO;
}

So in my service I have getUnitOfMeasureById(UUID id) that return a UnitOfMeasureDTO. Now I need to call, from another service, getUnitOfMeasureById(UUID id) that return the domain entity UnitOfMeasure. I think it's correct to call a service method from another service (not a controller method!) and the separation between business logic is at the service layer. So is it correct to have 2 methods: getUnitOfMeasureDTOById and getUnitOfMeasureById in the service? (getUnitOfMeasureDTOById call getUnitOfMeasureById to avoid code duplication)

Davide
  • 75
  • 1
  • 2
  • 11
  • this is an opinion question since there is no "correct" approach in software development. It is not wrong if that is what you wanted to hear. For future reference dont worry about "correct" - get it to work and then keep looking and revising it until you are happy with the solution (it is like writin an essay) – J Asgarov Apr 27 '21 at 13:39
  • In instances like those, I like to introduce an additional `Facade` layer whose role is entity-to-dto conversion, input validation, transactional boundaries, and sometimes even data access via repositories. This way, you keep your services in the domain scope, so to speak, operating on and returning plain entities, while facades represent isolated domain entry points that prevent entities from 'leaking' outsude the domain. Like J Asgarov pointed out, though, you need to find what works best for you – crizzis Apr 27 '21 at 19:31

0 Answers0