From 019bcc64111276c6dfc238f87e2514dd38235548 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 23 Apr 2023 18:49:35 +0400 Subject: [PATCH] added repositories, dtos, validator, changed services and controllers --- .../com/kalyshev/yan/WebConfiguration.java | 20 +++++ .../cabinet/controller/CabinetController.java | 66 +++++++------- .../yan/cabinet/controller/CabinetDto.java | 24 ++++++ .../kalyshev/yan/cabinet/model/Cabinet.java | 4 +- .../repository/CabinetNotFoundException.java | 7 ++ .../cabinet/repository/CabinetRepository.java | 7 ++ .../yan/cabinet/service/CabinetService.java | 70 +++++++-------- .../controller/ComputerController.java | 63 ++++++-------- .../yan/computer/controller/ComputerDto.java | 28 ++++++ .../kalyshev/yan/computer/model/Computer.java | 8 +- .../repository/ComputerNotFoundException.java | 7 ++ .../repository/ComputerRepository.java | 7 ++ .../yan/computer/service/ComputerService.java | 86 ++++++++++--------- .../monitor/controller/MonitorController.java | 45 ++++------ .../yan/monitor/controller/MonitorDto.java | 23 +++++ .../kalyshev/yan/monitor/model/Monitor.java | 9 +- .../repository/MonitorNotFoundException.java | 7 ++ .../monitor/repository/MonitorRepository.java | 7 ++ .../yan/monitor/service/MonitorService.java | 73 +++++++++------- .../yan/util/error/AdviceController.java | 37 ++++++++ .../util/validation/ValidationException.java | 9 ++ .../yan/util/validation/ValidatorUtil.java | 25 ++++++ .../kalyshev/yan/JpaComputerCabinetTests.java | 4 +- 23 files changed, 411 insertions(+), 225 deletions(-) create mode 100644 src/main/java/com/kalyshev/yan/WebConfiguration.java create mode 100644 src/main/java/com/kalyshev/yan/cabinet/controller/CabinetDto.java create mode 100644 src/main/java/com/kalyshev/yan/cabinet/repository/CabinetNotFoundException.java create mode 100644 src/main/java/com/kalyshev/yan/cabinet/repository/CabinetRepository.java create mode 100644 src/main/java/com/kalyshev/yan/computer/controller/ComputerDto.java create mode 100644 src/main/java/com/kalyshev/yan/computer/repository/ComputerNotFoundException.java create mode 100644 src/main/java/com/kalyshev/yan/computer/repository/ComputerRepository.java create mode 100644 src/main/java/com/kalyshev/yan/monitor/controller/MonitorDto.java create mode 100644 src/main/java/com/kalyshev/yan/monitor/repository/MonitorNotFoundException.java create mode 100644 src/main/java/com/kalyshev/yan/monitor/repository/MonitorRepository.java create mode 100644 src/main/java/com/kalyshev/yan/util/error/AdviceController.java create mode 100644 src/main/java/com/kalyshev/yan/util/validation/ValidationException.java create mode 100644 src/main/java/com/kalyshev/yan/util/validation/ValidatorUtil.java diff --git a/src/main/java/com/kalyshev/yan/WebConfiguration.java b/src/main/java/com/kalyshev/yan/WebConfiguration.java new file mode 100644 index 0000000..23baa3b --- /dev/null +++ b/src/main/java/com/kalyshev/yan/WebConfiguration.java @@ -0,0 +1,20 @@ +package com.kalyshev.yan; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfiguration implements WebMvcConfigurer { + public static final String REST_API = "/api"; + @Override + public void addViewControllers(ViewControllerRegistry registry) { + WebMvcConfigurer.super.addViewControllers(registry); + registry.addViewController("rest-test"); + } + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**").allowedMethods("*"); + } +} \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetController.java b/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetController.java index 411e97c..be60e5c 100644 --- a/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetController.java +++ b/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetController.java @@ -1,68 +1,60 @@ package com.kalyshev.yan.cabinet.controller; +import com.kalyshev.yan.WebConfiguration; +import com.kalyshev.yan.computer.controller.ComputerDto; import com.kalyshev.yan.computer.model.Computer; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import com.kalyshev.yan.monitor.controller.MonitorDto; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; import com.kalyshev.yan.cabinet.model.Cabinet; import com.kalyshev.yan.cabinet.service.CabinetService; import java.util.List; @RestController -@RequestMapping("/cabinet") +@RequestMapping(WebConfiguration.REST_API + "/cabinet") public class CabinetController { private final CabinetService cabinetService; - public CabinetController(CabinetService cabinetService) { this.cabinetService = cabinetService; } - @GetMapping("/{id}") - public Cabinet getCabinet(@PathVariable Long id) { - return cabinetService.findCabinet(id); + public CabinetDto getCabinet(@PathVariable Long id) { + return new CabinetDto(cabinetService.findCabinet(id)); } - @GetMapping("/") - public List getCabinets() { - return cabinetService.findAllCabinets(); + public List getCabinets() { + return cabinetService.findAllCabinets().stream() + .map(CabinetDto::new) + .toList(); } - @GetMapping("/{id}/computers") - public List getCabinetComputers(@PathVariable Long id) { - return cabinetService.listComputers(id); + public List getCabinetComputers(@PathVariable Long id) { + return cabinetService.listComputers(id).stream() + .map(ComputerDto::new) + .toList(); } - @PostMapping("/") - public Cabinet createCabinet(@RequestParam("number") String number) { - return cabinetService.addCabinet(number); + public CabinetDto createCabinet(@RequestBody @Valid CabinetDto cabinetDto) { + return new CabinetDto(cabinetService.addCabinet(cabinetDto.getNumber())); } - @PostMapping("/computer") - public Computer createCabinetComputer(@RequestParam("computerId") Long computerId, + public ComputerDto createCabinetComputer(@RequestParam("computerId") Long computerId, @RequestParam("cabinetId") Long cabinetId) { - return cabinetService.addComputer(computerId, cabinetId); + return new ComputerDto(cabinetService.addComputer(computerId, cabinetId)); } - - @PatchMapping("/{id}") - public Cabinet updateCabinet(@PathVariable Long id, - @RequestParam("number") String number) { - return cabinetService.updateCabinet(id, number); + @PutMapping("/{id}") + public CabinetDto updateCabinet(@PathVariable Long id, + @RequestBody @Valid CabinetDto cabinetDto) { + return new CabinetDto(cabinetService.updateCabinet(id, cabinetDto.getNumber())); } - @DeleteMapping("/{id}") - public Cabinet deleteCabinet(@PathVariable Long id) { - return cabinetService.deleteCabinet(id); + public CabinetDto deleteCabinet(@PathVariable Long id) { + return new CabinetDto(cabinetService.deleteCabinet(id)); } - @DeleteMapping("/{cabinetId}/computer") - public Computer deleteCabinetComputer(@PathVariable Long cabinetId, - @RequestParam("computerId") Long computerId) { - return cabinetService.deleteComputer(computerId, cabinetId); + public ComputerDto deleteCabinetComputer(@PathVariable Long cabinetId, + @RequestParam("computerId") Long computerId) { + return new ComputerDto(cabinetService.deleteComputer(computerId, cabinetId)); } } \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetDto.java b/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetDto.java new file mode 100644 index 0000000..f2426e4 --- /dev/null +++ b/src/main/java/com/kalyshev/yan/cabinet/controller/CabinetDto.java @@ -0,0 +1,24 @@ +package com.kalyshev.yan.cabinet.controller; + +import com.kalyshev.yan.cabinet.model.Cabinet; +import com.kalyshev.yan.computer.model.Computer; + +import java.util.List; + +public class CabinetDto { + private Long id; + private String number; + private List computers; + public CabinetDto() {} + public CabinetDto(Cabinet cabinet) { + this.id = cabinet.getId(); + this.number = cabinet.getNumber(); + this.computers = List.copyOf(cabinet.getComputers()); + } + public Long getId() { return this.id; } + public void setId(Long id) { this.id = id; } + public String getNumber() { return this.number; } + public void setNumber(String number) { this.number = number; } + public List getComputers() { return this.computers; } + public void setComputers(List computers) { this.computers = computers; } +} diff --git a/src/main/java/com/kalyshev/yan/cabinet/model/Cabinet.java b/src/main/java/com/kalyshev/yan/cabinet/model/Cabinet.java index b77a6ee..153c026 100644 --- a/src/main/java/com/kalyshev/yan/cabinet/model/Cabinet.java +++ b/src/main/java/com/kalyshev/yan/cabinet/model/Cabinet.java @@ -25,10 +25,10 @@ public class Cabinet { public Long getId() { return id; } - public String getnumber() { + public String getNumber() { return number; } - public void setnumber(String number) { + public void setNumber(String number) { this.number = number; } public List getComputers() { diff --git a/src/main/java/com/kalyshev/yan/cabinet/repository/CabinetNotFoundException.java b/src/main/java/com/kalyshev/yan/cabinet/repository/CabinetNotFoundException.java new file mode 100644 index 0000000..519e713 --- /dev/null +++ b/src/main/java/com/kalyshev/yan/cabinet/repository/CabinetNotFoundException.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.cabinet.repository; + +public class CabinetNotFoundException extends RuntimeException { + public CabinetNotFoundException(Long id) { + super(String.format("Cabinet with id [%s] is not found", id)); + } +} diff --git a/src/main/java/com/kalyshev/yan/cabinet/repository/CabinetRepository.java b/src/main/java/com/kalyshev/yan/cabinet/repository/CabinetRepository.java new file mode 100644 index 0000000..b8addbc --- /dev/null +++ b/src/main/java/com/kalyshev/yan/cabinet/repository/CabinetRepository.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.cabinet.repository; + +import com.kalyshev.yan.cabinet.model.Cabinet; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CabinetRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/cabinet/service/CabinetService.java b/src/main/java/com/kalyshev/yan/cabinet/service/CabinetService.java index a319426..66d7fcc 100644 --- a/src/main/java/com/kalyshev/yan/cabinet/service/CabinetService.java +++ b/src/main/java/com/kalyshev/yan/cabinet/service/CabinetService.java @@ -1,6 +1,11 @@ package com.kalyshev.yan.cabinet.service; +import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException; +import com.kalyshev.yan.cabinet.repository.CabinetRepository; import com.kalyshev.yan.computer.model.Computer; +import com.kalyshev.yan.computer.repository.ComputerNotFoundException; +import com.kalyshev.yan.computer.repository.ComputerRepository; +import com.kalyshev.yan.util.validation.ValidatorUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; @@ -10,37 +15,38 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.PersistenceContext; import java.util.List; +import java.util.Optional; @Service public class CabinetService { - @PersistenceContext - private EntityManager em; - + private final CabinetRepository cabinetRepository; + private final ComputerRepository computerRepository; + private final ValidatorUtil validatorUtil; + public CabinetService(CabinetRepository cabinetRepository, + ComputerRepository computerRepository, + ValidatorUtil validatorUtil) { + this.cabinetRepository = cabinetRepository; + this.computerRepository = computerRepository; + this.validatorUtil = validatorUtil; + } @Transactional public Cabinet addCabinet(String number) { if (!StringUtils.hasText(number)) { throw new IllegalArgumentException("Cabinet number is null or empty"); } final Cabinet cabinet = new Cabinet(number); - em.persist(cabinet); - return cabinet; + validatorUtil.validate(cabinet); + return cabinetRepository.save(cabinet); } - @Transactional(readOnly = true) public Cabinet findCabinet(Long id) { - final Cabinet cabinet = em.find(Cabinet.class, id); - if (cabinet == null) { - throw new EntityNotFoundException(String.format("Cabinet with id [%s] is not found", id)); - } - return cabinet; + final Optional cabinet = cabinetRepository.findById(id); + return cabinet.orElseThrow(() -> new CabinetNotFoundException(id)); } - @Transactional(readOnly = true) public List findAllCabinets() { - return em.createQuery("select s from Cabinet s", Cabinet.class) - .getResultList(); + return cabinetRepository.findAll(); } - @Transactional public Cabinet updateCabinet(Long id, String number) { if (!StringUtils.hasText(number)) { @@ -48,38 +54,33 @@ public class CabinetService { } final Cabinet currentCabinet = findCabinet(id); currentCabinet.setnumber(number); - return em.merge(currentCabinet); + validatorUtil.validate(currentCabinet); + return cabinetRepository.save(currentCabinet); } - @Transactional public Cabinet deleteCabinet(Long id) { final Cabinet currentCabinet = findCabinet(id); int size = currentCabinet.getComputers().size(); for (int i = 0; i < size; i++) { - Computer temp = currentCabinet.getComputers().get(i); - temp.setCabinet(null); - currentCabinet.removeComputer(temp); - em.remove(temp); + Computer computer = currentCabinet.getComputers().get(i); + computer.setCabinet(null); + currentCabinet.removeComputer(computer); + computerRepository.delete(computer); } - em.remove(currentCabinet); + cabinetRepository.delete(currentCabinet); return currentCabinet; } - @Transactional public void deleteAllCabinets() { - em.createQuery("delete from Cabinet").executeUpdate(); + cabinetRepository.deleteAll(); } - - @Transactional public List listComputers(Long id) { if ((Object)id == null) { throw new IllegalArgumentException("Cabinet id is null or empty"); } - final Cabinet cabinet = em.find(Cabinet.class, id); - return cabinet.getComputers(); + return findCabinet(id).getComputers(); } - @Transactional public Computer addComputer(Long computerId, Long cabinetId) { if ((Object)computerId == null) { @@ -88,12 +89,12 @@ public class CabinetService { if ((Object)cabinetId == null) { throw new IllegalArgumentException("Cabinet id is null or empty"); } - final Computer computer = em.find(Computer.class, computerId); - final Cabinet cabinet = em.find(Cabinet.class, cabinetId); + final Computer computer = computerRepository.findById(computerId) + .orElseThrow(() -> new ComputerNotFoundException(computerId)); + final Cabinet cabinet = findCabinet(cabinetId); cabinet.addComputer(computer); return computer; } - @Transactional public Computer deleteComputer(Long computerId, Long cabinetId) { if ((Object)computerId == null) { @@ -102,8 +103,9 @@ public class CabinetService { if ((Object)cabinetId == null) { throw new IllegalArgumentException("Cabinet id is null or empty"); } - final Computer computer = em.find(Computer.class, computerId); - final Cabinet cabinet = em.find(Cabinet.class, cabinetId); + final Computer computer = computerRepository.findById(computerId) + .orElseThrow(() -> new ComputerNotFoundException(computerId)); + final Cabinet cabinet = findCabinet(cabinetId); cabinet.removeComputer(computer); return computer; } diff --git a/src/main/java/com/kalyshev/yan/computer/controller/ComputerController.java b/src/main/java/com/kalyshev/yan/computer/controller/ComputerController.java index 1b4995b..fbbb1fd 100644 --- a/src/main/java/com/kalyshev/yan/computer/controller/ComputerController.java +++ b/src/main/java/com/kalyshev/yan/computer/controller/ComputerController.java @@ -1,68 +1,53 @@ package com.kalyshev.yan.computer.controller; +import com.kalyshev.yan.WebConfiguration; +import com.kalyshev.yan.cabinet.controller.CabinetDto; import com.kalyshev.yan.cabinet.model.Cabinet; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import com.kalyshev.yan.monitor.controller.MonitorDto; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; import com.kalyshev.yan.computer.model.Computer; import com.kalyshev.yan.computer.service.ComputerService; import java.util.List; @RestController -@RequestMapping("/computer") +@RequestMapping(WebConfiguration.REST_API + "/computer") public class ComputerController { private final ComputerService computerService; - public ComputerController(ComputerService computerService) { this.computerService = computerService; } - @GetMapping("/{id}") - public Computer getStudent(@PathVariable Long id) { - return computerService.findComputer(id); + public ComputerDto getStudent(@PathVariable Long id) { + return new ComputerDto(computerService.findComputer(id)); } - @GetMapping("/") - public List getComputers() { - return computerService.findAllComputers(); + public List getComputers() { + return computerService.findAllComputers().stream() + .map(ComputerDto::new) + .toList(); } - @GetMapping("/{id}/computers") - public Cabinet getComputersCabinet(@PathVariable Long id) { - return computerService.getCabinet(id); + public CabinetDto getComputersCabinet(@PathVariable Long id) { + return new CabinetDto(computerService.getCabinet(id)); } - @PostMapping("/") - public Computer createComputer(@RequestParam("modelName") String modelName, - @RequestParam("serialNum") String serialNum, - @RequestParam("monitorId") Long monitorId, - @RequestParam("cabinetId") Long cabinetId) { - return computerService.addComputer(modelName, serialNum, monitorId, cabinetId); + public ComputerDto createComputer(@RequestBody @Valid ComputerDto computerDto) { + return new ComputerDto(computerService.addComputer(computerDto.getModelName(), computerDto.getSerialNum(), computerDto.getMonitorId(), computerDto.getCabinetId())); } - @PostMapping("/cabinet") - public Cabinet setCabinetComputer(@RequestParam("computerId") Long computerId, + public CabinetDto setCabinetComputer(@RequestParam("computerId") Long computerId, @RequestParam("cabinetId") Long cabinetId) { - return computerService.setCabinet(cabinetId, computerId); + return new CabinetDto(computerService.setCabinet(cabinetId, computerId)); } - - @PatchMapping("/{id}") - public Computer updateComputer(@PathVariable Long id, - @RequestParam("modelName") String modelName, - @RequestParam("serialNum") String serialNum, - @RequestParam("monitorId") Long monitorId, - @RequestParam("cabinetId") Long cabinetId) { - return computerService.updateComputer(id, modelName, serialNum, monitorId, cabinetId); + @PutMapping("/{id}") + public ComputerDto updateComputer(@PathVariable Long id, + @RequestBody @Valid ComputerDto computerDto) { + return new ComputerDto(computerService.updateComputer(id, computerDto.getModelName(), computerDto.getSerialNum(), computerDto.getMonitorId(), computerDto.getCabinetId())); } - @DeleteMapping("/{id}") - public Computer deleteComputer(@PathVariable Long id) { - return computerService.deleteComputer(id); + public ComputerDto deleteComputer(@PathVariable Long id) { + return new ComputerDto(computerService.deleteComputer(id)); } } \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/computer/controller/ComputerDto.java b/src/main/java/com/kalyshev/yan/computer/controller/ComputerDto.java new file mode 100644 index 0000000..e8bdeba --- /dev/null +++ b/src/main/java/com/kalyshev/yan/computer/controller/ComputerDto.java @@ -0,0 +1,28 @@ +package com.kalyshev.yan.computer.controller; + +import com.kalyshev.yan.computer.model.Computer; + +public class ComputerDto { + private Long id; + private String modelName; + private String serialNum; + private Long monitorId; + private Long cabinetId; + public ComputerDto() {} + public ComputerDto(Computer computer) { + this.id = computer.getId(); + this.modelName = computer.getModelName(); + this.serialNum = computer.getSerialNum(); + this.monitorId = computer.getMonitor().getId(); + this.cabinetId = computer.getCabinet().getId(); + } + public Long getId() { return this.id; } + public String getModelName() { return this.modelName; } + public void setModelName(String modelName) { this.modelName = modelName; } + public String getSerialNum() { return this.serialNum; } + public void setSerialNum(String serialNum) { this.serialNum = serialNum; } + public Long getMonitorId() { return this.monitorId; } + public void setMonitorId(Long monitorId) { this.monitorId = monitorId; } + public Long getCabinetId() { return this.cabinetId; } + public void setCabinetId(Long cabinetId) { this.cabinetId = cabinetId; } +} diff --git a/src/main/java/com/kalyshev/yan/computer/model/Computer.java b/src/main/java/com/kalyshev/yan/computer/model/Computer.java index fbda6c2..ed3bb6d 100644 --- a/src/main/java/com/kalyshev/yan/computer/model/Computer.java +++ b/src/main/java/com/kalyshev/yan/computer/model/Computer.java @@ -33,16 +33,16 @@ public class Computer { public Long getId() { return id; } - public String getmodelName() { + public String getModelName() { return modelName; } - public void setmodelName(String modelName) { + public void setModelName(String modelName) { this.modelName = modelName; } - public String getserialNum() { + public String getSerialNum() { return serialNum; } - public void setserialNum(String serialNum) { this.serialNum = serialNum; } + public void setSerialNum(String serialNum) { this.serialNum = serialNum; } public Cabinet getCabinet() { return cabinet; } public void setCabinet(Cabinet cabinet) { this.cabinet = cabinet; } diff --git a/src/main/java/com/kalyshev/yan/computer/repository/ComputerNotFoundException.java b/src/main/java/com/kalyshev/yan/computer/repository/ComputerNotFoundException.java new file mode 100644 index 0000000..a6a3750 --- /dev/null +++ b/src/main/java/com/kalyshev/yan/computer/repository/ComputerNotFoundException.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.computer.repository; + +public class ComputerNotFoundException extends RuntimeException { + public ComputerNotFoundException(Long id) { + super(String.format("Computer with id [%s] is not found", id)); + } +} \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/computer/repository/ComputerRepository.java b/src/main/java/com/kalyshev/yan/computer/repository/ComputerRepository.java new file mode 100644 index 0000000..1dc8c56 --- /dev/null +++ b/src/main/java/com/kalyshev/yan/computer/repository/ComputerRepository.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.computer.repository; + +import com.kalyshev.yan.computer.model.Computer; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ComputerRepository extends JpaRepository { +} diff --git a/src/main/java/com/kalyshev/yan/computer/service/ComputerService.java b/src/main/java/com/kalyshev/yan/computer/service/ComputerService.java index f2c30df..1d9afe2 100644 --- a/src/main/java/com/kalyshev/yan/computer/service/ComputerService.java +++ b/src/main/java/com/kalyshev/yan/computer/service/ComputerService.java @@ -1,25 +1,39 @@ package com.kalyshev.yan.computer.service; import com.kalyshev.yan.cabinet.model.Cabinet; +import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException; +import com.kalyshev.yan.cabinet.repository.CabinetRepository; +import com.kalyshev.yan.computer.repository.ComputerNotFoundException; +import com.kalyshev.yan.computer.repository.ComputerRepository; import com.kalyshev.yan.monitor.model.Monitor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.kalyshev.yan.monitor.repository.MonitorNotFoundException; +import com.kalyshev.yan.monitor.repository.MonitorRepository; +import com.kalyshev.yan.util.validation.ValidatorUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import com.kalyshev.yan.computer.model.Computer; -import jakarta.persistence.EntityManager; import jakarta.persistence.EntityNotFoundException; -import jakarta.persistence.PersistenceContext; + import java.util.List; +import java.util.Optional; @Service public class ComputerService { - private static final Logger log = LoggerFactory.getLogger(ComputerService.class); - @PersistenceContext - private EntityManager em; - + private final CabinetRepository cabinetRepository; + private final ComputerRepository computerRepository; + private final MonitorRepository monitorRepository; + private final ValidatorUtil validatorUtil; + public ComputerService(CabinetRepository cabinetRepository, + ComputerRepository computerRepository, + MonitorRepository monitorRepository, + ValidatorUtil validatorUtil) { + this.cabinetRepository = cabinetRepository; + this.computerRepository = computerRepository; + this.monitorRepository = monitorRepository; + this.validatorUtil = validatorUtil; + } @Transactional public Computer addComputer(String modelName, String serialNum, Long monitorId, Long cabinetId) { if (!StringUtils.hasText(modelName)) { @@ -30,38 +44,27 @@ public class ComputerService { } final Computer computer = new Computer(modelName, serialNum); if (monitorId != null) { - final Monitor monitor = em.find(Monitor.class, monitorId); - if (monitor == null) { - throw new IllegalArgumentException(String.format("Monitor with id [%s] not found", monitorId)); - } + final Monitor monitor = monitorRepository.findById(monitorId) + .orElseThrow(() -> new ComputerNotFoundException(monitorId)); computer.setMonitor(monitor); } if (cabinetId != null) { - final Cabinet cabinet = em.find(Cabinet.class, cabinetId); - if (cabinet == null) { - throw new IllegalArgumentException(String.format("Cabinet with id [%s] not found", cabinetId)); - } + final Cabinet cabinet = cabinetRepository.findById(cabinetId) + .orElseThrow(() -> new CabinetNotFoundException(cabinetId)); computer.setCabinet(cabinet); } - em.persist(computer); - return computer; + validatorUtil.validate(computer); + return computerRepository.save(computer); } - @Transactional(readOnly = true) public Computer findComputer(Long id) { - final Computer computer = em.find(Computer.class, id); - if (computer == null) { - throw new EntityNotFoundException(String.format("Computer with id [%s] not found", id)); - } - return computer; + final Optional computer = computerRepository.findById(id); + return computer.orElseThrow(() -> new ComputerNotFoundException(id)); } - @Transactional(readOnly = true) public List findAllComputers() { - return em.createQuery("select s from Computer s", Computer.class) - .getResultList(); + return computerRepository.findAll(); } - @Transactional public Computer updateComputer(Long id, String modelName, String serialNum, Long monitorId, Long cabinetId) { if (!(StringUtils.hasText(modelName) || StringUtils.hasText(serialNum))) { @@ -75,16 +78,18 @@ public class ComputerService { currentComputer.setserialNum(serialNum); } if (monitorId != null) { - Monitor monitor = em.find(Monitor.class, monitorId); + Monitor monitor = monitorRepository.findById(monitorId) + .orElseThrow(() -> new MonitorNotFoundException(id)); currentComputer.setMonitor(monitor); } if (cabinetId != null) { - Cabinet cabinet = em.find(Cabinet.class, cabinetId); + Cabinet cabinet = cabinetRepository.findById(cabinetId) + .orElseThrow(() -> new CabinetNotFoundException(cabinetId)); currentComputer.setCabinet(cabinet); } - return em.merge(currentComputer); + validatorUtil.validate(currentComputer); + return computerRepository.save(currentComputer); } - @Transactional public Computer deleteComputer(Long id) { final Computer currentComputer = findComputer(id); @@ -92,24 +97,24 @@ public class ComputerService { if (currentComputerCabinet != null) { currentComputerCabinet.removeComputer(currentComputer); } - em.remove(currentComputer); + computerRepository.delete(currentComputer); return currentComputer; } - @Transactional public void deleteAllComputers() { - em.createQuery("delete from Computer").executeUpdate(); + List computers = findAllComputers(); + for (Computer computer : computers) { + deleteComputer(computer.getId()); + } } - @Transactional public Cabinet getCabinet(Long id) { if ((Object)id == null) { throw new IllegalArgumentException("Computer id is null or empty"); } - final Computer computer = em.find(Computer.class, id); + final Computer computer = findComputer(id); return computer.getCabinet(); } - @Transactional public Cabinet setCabinet(Long cabinetId, Long computerId) { if ((Object)computerId == null) { @@ -118,8 +123,9 @@ public class ComputerService { if ((Object)cabinetId == null) { throw new IllegalArgumentException("Cabinet id is null or empty"); } - final Computer computer = em.find(Computer.class, computerId); - final Cabinet cabinet = em.find(Cabinet.class, cabinetId); + final Computer computer = findComputer(computerId); + final Cabinet cabinet = cabinetRepository.findById(cabinetId) + .orElseThrow(() -> new CabinetNotFoundException(cabinetId)); computer.setCabinet(cabinet); return cabinet; } diff --git a/src/main/java/com/kalyshev/yan/monitor/controller/MonitorController.java b/src/main/java/com/kalyshev/yan/monitor/controller/MonitorController.java index 6aae5df..c9c78fd 100644 --- a/src/main/java/com/kalyshev/yan/monitor/controller/MonitorController.java +++ b/src/main/java/com/kalyshev/yan/monitor/controller/MonitorController.java @@ -1,50 +1,41 @@ package com.kalyshev.yan.monitor.controller; +import com.kalyshev.yan.WebConfiguration; import com.kalyshev.yan.monitor.model.Monitor; import com.kalyshev.yan.monitor.service.MonitorService; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.*; import java.util.List; @RestController -@RequestMapping("/monitor") +@RequestMapping(WebConfiguration.REST_API + "/monitor") public class MonitorController { private final MonitorService monitorService; - public MonitorController(MonitorService monitorService) { this.monitorService = monitorService; } - @GetMapping("/{id}") - public Monitor getMonitor(@PathVariable Long id) { - return monitorService.findMonitor(id); + public MonitorDto getMonitor(@PathVariable Long id) { + return new MonitorDto(monitorService.findMonitor(id)); } - @GetMapping("/") - public List getMonitors() { - return monitorService.findAllMonitors(); + public List getMonitors() { + return monitorService.findAllMonitors().stream() + .map(MonitorDto::new) + .toList(); } - @PostMapping("/") - public Monitor createMonitor(@RequestParam("modelName") String modelName) { - return monitorService.addMonitor(modelName); + public MonitorDto createMonitor(@RequestBody @Valid MonitorDto monitorDto) { + return new MonitorDto(monitorService.addMonitor(monitorDto.getModelName())); } - - @PatchMapping("/{id}") - public Monitor updateMonitor(@PathVariable Long id, - @RequestParam("modelName") String modelName) { - return monitorService.updateMonitor(id, modelName); + @PutMapping("/{id}") + public MonitorDto updateMonitor(@PathVariable Long id, + @RequestBody @Valid MonitorDto monitorDto) { + return new MonitorDto(monitorService.updateMonitor(id, monitorDto.getModelName())); } - @DeleteMapping("/{id}") - public Monitor deleteMonitor(@PathVariable Long id) { - return monitorService.deleteMonitor(id); + public MonitorDto deleteMonitor(@PathVariable Long id) { + return new MonitorDto(monitorService.deleteMonitor(id)); } } \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/monitor/controller/MonitorDto.java b/src/main/java/com/kalyshev/yan/monitor/controller/MonitorDto.java new file mode 100644 index 0000000..a26947f --- /dev/null +++ b/src/main/java/com/kalyshev/yan/monitor/controller/MonitorDto.java @@ -0,0 +1,23 @@ +package com.kalyshev.yan.monitor.controller; + +import com.kalyshev.yan.monitor.model.Monitor; + +public class MonitorDto { + private Long id; + private String modelName; + public MonitorDto() { + } + public MonitorDto(Monitor monitor) { + this.id = monitor.getId(); + this.modelName = monitor.getModelName(); + } + public Long getId() { + return id; + } + public String getModelName() { + return modelName; + } + public void setModelName(String modelName) { + this.modelName = modelName; + } +} diff --git a/src/main/java/com/kalyshev/yan/monitor/model/Monitor.java b/src/main/java/com/kalyshev/yan/monitor/model/Monitor.java index 6ce47a6..b8978c4 100644 --- a/src/main/java/com/kalyshev/yan/monitor/model/Monitor.java +++ b/src/main/java/com/kalyshev/yan/monitor/model/Monitor.java @@ -13,23 +13,20 @@ public class Monitor { @GeneratedValue private Long id; private String modelName; - public Monitor() { } public Monitor(String modelName) { this.modelName = modelName; } - public Long getId() { return id; } - public String getmodelName() { + public String getModelName() { return modelName; } - public void setmodelName(String modelName) { + public void setModelName(String modelName) { this.modelName = modelName; } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -37,12 +34,10 @@ public class Monitor { Monitor computer = (Monitor) o; return Objects.equals(id, computer.id); } - @Override public int hashCode() { return Objects.hash(id); } - @Override public String toString() { return "Monitor{" + diff --git a/src/main/java/com/kalyshev/yan/monitor/repository/MonitorNotFoundException.java b/src/main/java/com/kalyshev/yan/monitor/repository/MonitorNotFoundException.java new file mode 100644 index 0000000..5a40a2b --- /dev/null +++ b/src/main/java/com/kalyshev/yan/monitor/repository/MonitorNotFoundException.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.monitor.repository; + +public class MonitorNotFoundException extends RuntimeException { + public MonitorNotFoundException(Long id) { + super(String.format("Monitor with id [%s] is not found", id)); + } +} \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/monitor/repository/MonitorRepository.java b/src/main/java/com/kalyshev/yan/monitor/repository/MonitorRepository.java new file mode 100644 index 0000000..610ab3c --- /dev/null +++ b/src/main/java/com/kalyshev/yan/monitor/repository/MonitorRepository.java @@ -0,0 +1,7 @@ +package com.kalyshev.yan.monitor.repository; + +import com.kalyshev.yan.monitor.model.Monitor; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MonitorRepository extends JpaRepository { +} diff --git a/src/main/java/com/kalyshev/yan/monitor/service/MonitorService.java b/src/main/java/com/kalyshev/yan/monitor/service/MonitorService.java index d172b3b..3f4e5e3 100644 --- a/src/main/java/com/kalyshev/yan/monitor/service/MonitorService.java +++ b/src/main/java/com/kalyshev/yan/monitor/service/MonitorService.java @@ -1,6 +1,13 @@ package com.kalyshev.yan.monitor.service; +import com.kalyshev.yan.cabinet.model.Cabinet; +import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException; +import com.kalyshev.yan.cabinet.repository.CabinetRepository; import com.kalyshev.yan.computer.model.Computer; +import com.kalyshev.yan.computer.repository.ComputerRepository; +import com.kalyshev.yan.monitor.repository.MonitorNotFoundException; +import com.kalyshev.yan.monitor.repository.MonitorRepository; +import com.kalyshev.yan.util.validation.ValidatorUtil; import jakarta.persistence.TypedQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,72 +21,72 @@ import jakarta.persistence.EntityNotFoundException; import jakarta.persistence.PersistenceContext; import java.util.List; import java.util.Objects; +import java.util.Optional; @Service public class MonitorService { - private static final Logger log = LoggerFactory.getLogger(MonitorService.class); - @PersistenceContext - private EntityManager em; - + private final MonitorRepository monitorRepository; + private final ComputerRepository computerRepository; + private final ValidatorUtil validatorUtil; + public MonitorService(MonitorRepository monitorRepository, + ComputerRepository computerRepository, + ValidatorUtil validatorUtil) { + this.monitorRepository = monitorRepository; + this.computerRepository = computerRepository; + this.validatorUtil = validatorUtil; + } @Transactional public Monitor addMonitor(String modelName) { if (!StringUtils.hasText(modelName)) { throw new IllegalArgumentException("Monitor model name is null or empty"); } final Monitor monitor = new Monitor(modelName); - em.persist(monitor); - return monitor; + validatorUtil.validate(monitor); + return monitorRepository.save(monitor); } - @Transactional(readOnly = true) public Monitor findMonitor(Long id) { - final Monitor monitor = em.find(Monitor.class, id); - if (monitor == null) { - throw new EntityNotFoundException(String.format("Monitor with id [%s] is not found", id)); - } - return monitor; + final Optional monitor = monitorRepository.findById(id); + return monitor.orElseThrow(() -> new MonitorNotFoundException(id)); } - @Transactional(readOnly = true) public List findAllMonitors() { - return em.createQuery("select s from Monitor s", Monitor.class) - .getResultList(); + return monitorRepository.findAll(); } - @Transactional public Monitor updateMonitor(Long id, String modelName) { if (!StringUtils.hasText(modelName)) { throw new IllegalArgumentException("Monitor model name is null or empty"); } final Monitor currentMonitor = findMonitor(id); - currentMonitor.setmodelName(modelName); - return em.merge(currentMonitor); + currentMonitor.setModelName(modelName); + validatorUtil.validate(currentMonitor); + return monitorRepository.save(currentMonitor); } - @Transactional public Monitor deleteMonitor(Long id) { final Monitor currentMonitor = findMonitor(id); - em.remove(currentMonitor); + Computer computer = getComputer(id); + computer.removeMonitor(); + monitorRepository.delete(currentMonitor); return currentMonitor; } - @Transactional public void deleteAllMonitors() { - List listComps = em.createQuery("select s from Computer s", Computer.class).getResultList(); - for (int i = 0; i < listComps.size(); i++){ - listComps.get(i).removeMonitor(); - } - List listMons = em.createQuery("select s from Monitor s", Monitor.class).getResultList(); - for (int i = 0; i < listMons.size(); i++){ - deleteMonitor(listMons.get(i).getId()); + List computers = computerRepository.findAll(); + for (Computer computer : computers) { + computer.removeMonitor(); } + monitorRepository.deleteAll(); } - @Transactional public Computer getComputer(Long id) { - Computer computer = em.createQuery("select s from Computer s where s.monitor.id = :id", Computer.class) - .setParameter("id", id) - .getSingleResult(); - return computer; + List computers = computerRepository.findAll(); + for (Computer computer : computers) { + if (Objects.equals(computer.getMonitor().getId(), id)) { + return computer; + } + } + return null; } } \ No newline at end of file diff --git a/src/main/java/com/kalyshev/yan/util/error/AdviceController.java b/src/main/java/com/kalyshev/yan/util/error/AdviceController.java new file mode 100644 index 0000000..63f9aec --- /dev/null +++ b/src/main/java/com/kalyshev/yan/util/error/AdviceController.java @@ -0,0 +1,37 @@ +package com.kalyshev.yan.util.error; + +import com.kalyshev.yan.cabinet.repository.CabinetNotFoundException; +import com.kalyshev.yan.util.validation.ValidationException; +import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; + +import java.util.stream.Collectors; + +@ControllerAdvice(annotations = RestController.class) +public class AdviceController { + @ExceptionHandler({ + CabinetNotFoundException.class, + ValidationException.class + }) + public ResponseEntity handleException(Throwable e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleBindException(MethodArgumentNotValidException e) { + final ValidationException validationException = new ValidationException( + e.getBindingResult().getAllErrors().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.toSet())); + return handleException(validationException); + } + @ExceptionHandler(Exception.class) + public ResponseEntity handleUnknownException(Throwable e) { + e.printStackTrace(); + return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/com/kalyshev/yan/util/validation/ValidationException.java b/src/main/java/com/kalyshev/yan/util/validation/ValidationException.java new file mode 100644 index 0000000..8c5664f --- /dev/null +++ b/src/main/java/com/kalyshev/yan/util/validation/ValidationException.java @@ -0,0 +1,9 @@ +package com.kalyshev.yan.util.validation; + +import java.util.Set; + +public class ValidationException extends RuntimeException { + public ValidationException(Set errors) { + super(String.join("\n", errors)); + } +} diff --git a/src/main/java/com/kalyshev/yan/util/validation/ValidatorUtil.java b/src/main/java/com/kalyshev/yan/util/validation/ValidatorUtil.java new file mode 100644 index 0000000..d46a447 --- /dev/null +++ b/src/main/java/com/kalyshev/yan/util/validation/ValidatorUtil.java @@ -0,0 +1,25 @@ +package com.kalyshev.yan.util.validation; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import org.springframework.stereotype.Component; + +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class ValidatorUtil { + private final Validator validator; + public ValidatorUtil() { + this.validator = Validation.buildDefaultValidatorFactory().getValidator(); + } + public void validate(T object) { + final Set> errors = validator.validate(object); + if (!errors.isEmpty()) { + throw new ValidationException(errors.stream() + .map(ConstraintViolation::getMessage) + .collect(Collectors.toSet())); + } + } +} diff --git a/src/test/java/com/kalyshev/yan/JpaComputerCabinetTests.java b/src/test/java/com/kalyshev/yan/JpaComputerCabinetTests.java index 60d7580..82cf29c 100644 --- a/src/test/java/com/kalyshev/yan/JpaComputerCabinetTests.java +++ b/src/test/java/com/kalyshev/yan/JpaComputerCabinetTests.java @@ -34,7 +34,7 @@ public class JpaComputerCabinetTests { cabinet.addComputer(computer); log.info(cabinet.toString()); log.info(computer.toString()); - Assertions.assertEquals(cabinet.getComputers().get(0).getserialNum(), computer.getserialNum()); + Assertions.assertEquals(cabinet.getComputers().get(0).getSerialNum(), computer.getSerialNum()); } @Test @@ -48,7 +48,7 @@ public class JpaComputerCabinetTests { cabinet.addComputer(computer); log.info(cabinet.toString()); log.info(computer.toString()); - Assertions.assertEquals(cabinet.getComputers().get(0).getserialNum(), computer.getserialNum()); + Assertions.assertEquals(cabinet.getComputers().get(0).getSerialNum(), computer.getSerialNum()); cabinet.removeComputer(computer); Assertions.assertEquals(cabinet.getComputers().size(), 0); }