From 5bb2718548af88944e567a59abaeea626beb4723 Mon Sep 17 00:00:00 2001 From: Dyego dos Santos Brito Date: Thu, 12 Jan 2023 20:10:31 -0300 Subject: [PATCH 1/3] Validation deleteShouldReturnNotFoundWhenNonExistingId --- .../java/com/devsuperior/bds02/controllers/CityControllerIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/devsuperior/bds02/controllers/CityControllerIT.java b/src/test/java/com/devsuperior/bds02/controllers/CityControllerIT.java index d5b4257b..e0ad0589 100644 --- a/src/test/java/com/devsuperior/bds02/controllers/CityControllerIT.java +++ b/src/test/java/com/devsuperior/bds02/controllers/CityControllerIT.java @@ -81,6 +81,7 @@ public void deleteShouldReturnNotFoundWhenNonExistingId() throws Exception { mockMvc.perform(delete("/cities/{id}", nonExistingId)); result.andExpect(status().isNotFound()); + result.andExpect(jsonPath("$.message").isNotEmpty()); } @Test From 0eca70b794fdcccdc273d55f70c77d18d5f15d90 Mon Sep 17 00:00:00 2001 From: Dyego dos Santos Brito Date: Thu, 12 Jan 2023 20:58:28 -0300 Subject: [PATCH 2/3] Validation updateShouldReturnNotFoundWhenIdDoesNotExist --- .../com/devsuperior/bds02/controllers/EventControllerIT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/devsuperior/bds02/controllers/EventControllerIT.java b/src/test/java/com/devsuperior/bds02/controllers/EventControllerIT.java index e622e339..cf74e6f8 100644 --- a/src/test/java/com/devsuperior/bds02/controllers/EventControllerIT.java +++ b/src/test/java/com/devsuperior/bds02/controllers/EventControllerIT.java @@ -67,5 +67,6 @@ public void updateShouldReturnNotFoundWhenIdDoesNotExist() throws Exception { .accept(MediaType.APPLICATION_JSON)); result.andExpect(status().isNotFound()); + result.andExpect(jsonPath("$.message").isNotEmpty()); } } From 4d2a8ea4b39698ec33178c4522f91d8c0412206e Mon Sep 17 00:00:00 2001 From: Dyego dos Santos Brito Date: Thu, 12 Jan 2023 21:53:57 -0300 Subject: [PATCH 3/3] Tests passing --- .../bds02/controllers/CityController.java | 48 +++++++++++++++ .../bds02/controllers/EventController.java | 26 ++++++++ .../exceptions/ResourceExceptionHandler.java | 45 ++++++++++++++ .../controllers/exceptions/StandardError.java | 59 +++++++++++++++++++ .../bds02/repositories/CityRepository.java | 11 ++++ .../bds02/repositories/EventRepository.java | 11 ++++ .../bds02/services/CityService.java | 50 ++++++++++++++++ .../bds02/services/EventService.java | 39 ++++++++++++ .../exceptions/DatabaseException.java | 10 ++++ .../exceptions/ResourceNotFoundException.java | 10 ++++ 10 files changed, 309 insertions(+) create mode 100644 src/main/java/com/devsuperior/bds02/controllers/CityController.java create mode 100644 src/main/java/com/devsuperior/bds02/controllers/EventController.java create mode 100644 src/main/java/com/devsuperior/bds02/controllers/exceptions/ResourceExceptionHandler.java create mode 100644 src/main/java/com/devsuperior/bds02/controllers/exceptions/StandardError.java create mode 100644 src/main/java/com/devsuperior/bds02/repositories/CityRepository.java create mode 100644 src/main/java/com/devsuperior/bds02/repositories/EventRepository.java create mode 100644 src/main/java/com/devsuperior/bds02/services/CityService.java create mode 100644 src/main/java/com/devsuperior/bds02/services/EventService.java create mode 100644 src/main/java/com/devsuperior/bds02/services/exceptions/DatabaseException.java create mode 100644 src/main/java/com/devsuperior/bds02/services/exceptions/ResourceNotFoundException.java diff --git a/src/main/java/com/devsuperior/bds02/controllers/CityController.java b/src/main/java/com/devsuperior/bds02/controllers/CityController.java new file mode 100644 index 00000000..da2fc668 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/controllers/CityController.java @@ -0,0 +1,48 @@ +package com.devsuperior.bds02.controllers; + +import java.net.URI; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.devsuperior.bds02.dto.CityDTO; +import com.devsuperior.bds02.services.CityService; + +@RestController +@RequestMapping(value = "/cities") +public class CityController { + + @Autowired + private CityService service; + + @GetMapping + public ResponseEntity> findAll() { + List list = service.findAll(); + return ResponseEntity.ok().body(list); + } + + @PostMapping + public ResponseEntity insert(@RequestBody CityDTO dto) { + dto = service.insert(dto); + + URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}") + .buildAndExpand(dto.getId()).toUri(); + + return ResponseEntity.created(uri).body(dto); + } + + @DeleteMapping(value = "/{id}") + public ResponseEntity delete(@PathVariable Long id) { + service.delete(id); + return ResponseEntity.noContent().build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/controllers/EventController.java b/src/main/java/com/devsuperior/bds02/controllers/EventController.java new file mode 100644 index 00000000..bdb99fce --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/controllers/EventController.java @@ -0,0 +1,26 @@ +package com.devsuperior.bds02.controllers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.devsuperior.bds02.dto.EventDTO; +import com.devsuperior.bds02.services.EventService; + +@RestController +@RequestMapping(value = "/events") +public class EventController { + + @Autowired + private EventService service; + + @PutMapping(value = "/{id}") + public ResponseEntity update(@PathVariable Long id, @RequestBody EventDTO dto) { + dto = service.update(id, dto); + return ResponseEntity.ok().body(dto); + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/controllers/exceptions/ResourceExceptionHandler.java b/src/main/java/com/devsuperior/bds02/controllers/exceptions/ResourceExceptionHandler.java new file mode 100644 index 00000000..ef7e82e6 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/controllers/exceptions/ResourceExceptionHandler.java @@ -0,0 +1,45 @@ +package com.devsuperior.bds02.controllers.exceptions; + +import java.time.Instant; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import com.devsuperior.bds02.services.exceptions.DatabaseException; +import com.devsuperior.bds02.services.exceptions.ResourceNotFoundException; + +@ControllerAdvice +public class ResourceExceptionHandler { + + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity entityNotFound(ResourceNotFoundException e, HttpServletRequest request) { + HttpStatus status = HttpStatus.NOT_FOUND; + + StandardError err = new StandardError(); + err.setTimestamp(Instant.now()); + err.setStatus(status.value()); + err.setError("Resource not found"); + err.setMessage(e.getMessage()); + err.setPath(request.getRequestURI()); + + return ResponseEntity.status(status).body(err); + } + + @ExceptionHandler(DatabaseException.class) + public ResponseEntity database(DatabaseException e, HttpServletRequest request) { + HttpStatus status = HttpStatus.BAD_REQUEST; + + StandardError err = new StandardError(); + err.setTimestamp(Instant.now()); + err.setStatus(status.value()); + err.setError("Database exception"); + err.setMessage(e.getMessage()); + err.setPath(request.getRequestURI()); + + return ResponseEntity.status(status).body(err); + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/controllers/exceptions/StandardError.java b/src/main/java/com/devsuperior/bds02/controllers/exceptions/StandardError.java new file mode 100644 index 00000000..f60c0f5b --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/controllers/exceptions/StandardError.java @@ -0,0 +1,59 @@ +package com.devsuperior.bds02.controllers.exceptions; + +import java.io.Serializable; +import java.time.Instant; + +public class StandardError implements Serializable { + + private static final long serialVersionUID = 1L; + + private Instant timestamp; + private Integer status; + private String error; + private String message; + private String path; + + public StandardError() { + + } + + public Instant getTimestamp() { + return timestamp; + } + + public void setTimestamp(Instant timestamp) { + this.timestamp = timestamp; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/repositories/CityRepository.java b/src/main/java/com/devsuperior/bds02/repositories/CityRepository.java new file mode 100644 index 00000000..4989c599 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/repositories/CityRepository.java @@ -0,0 +1,11 @@ +package com.devsuperior.bds02.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.devsuperior.bds02.entities.City; + +@Repository +public interface CityRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/repositories/EventRepository.java b/src/main/java/com/devsuperior/bds02/repositories/EventRepository.java new file mode 100644 index 00000000..ce9404e0 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/repositories/EventRepository.java @@ -0,0 +1,11 @@ +package com.devsuperior.bds02.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.devsuperior.bds02.entities.Event; + +@Repository +public interface EventRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/services/CityService.java b/src/main/java/com/devsuperior/bds02/services/CityService.java new file mode 100644 index 00000000..d55c24f1 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/services/CityService.java @@ -0,0 +1,50 @@ +package com.devsuperior.bds02.services; + +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.devsuperior.bds02.dto.CityDTO; +import com.devsuperior.bds02.entities.City; +import com.devsuperior.bds02.repositories.CityRepository; +import com.devsuperior.bds02.services.exceptions.DatabaseException; +import com.devsuperior.bds02.services.exceptions.ResourceNotFoundException; + +@Service +public class CityService { + + @Autowired + private CityRepository repository; + + @Transactional(readOnly = true) + public List findAll() { + List list = repository.findAll(Sort.by("name")); + return list.stream().map(x -> new CityDTO(x)).collect(Collectors.toList()); + } + + @Transactional + public CityDTO insert(CityDTO dto) { + City entity = new City(); + entity.setName(dto.getName()); + + entity = repository.save(entity); + + return new CityDTO(entity); + } + + public void delete(Long id) { + try { + repository.deleteById(id); + } catch (EmptyResultDataAccessException e) { + throw new ResourceNotFoundException("Id not found " + id); + } catch (DataIntegrityViolationException e) { + throw new DatabaseException("Integrity violation"); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/services/EventService.java b/src/main/java/com/devsuperior/bds02/services/EventService.java new file mode 100644 index 00000000..7769eee3 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/services/EventService.java @@ -0,0 +1,39 @@ +package com.devsuperior.bds02.services; + +import javax.persistence.EntityNotFoundException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.devsuperior.bds02.dto.EventDTO; +import com.devsuperior.bds02.entities.City; +import com.devsuperior.bds02.entities.Event; +import com.devsuperior.bds02.repositories.EventRepository; +import com.devsuperior.bds02.services.exceptions.ResourceNotFoundException; + +@Service +public class EventService { + + @Autowired + private EventRepository repository; + + @Transactional + public EventDTO update(Long id, EventDTO dto) { + try { + Event entity = repository.getOne(id); + copyDtoToEntity(dto, entity); + entity = repository.save(entity); + return new EventDTO(entity); + } catch (EntityNotFoundException e) { + throw new ResourceNotFoundException("Id not found " + id); + } + } + + private void copyDtoToEntity(EventDTO dto, Event entity) { + entity.setName(dto.getName()); + entity.setDate(dto.getDate()); + entity.setUrl(dto.getUrl()); + entity.setCity(new City(dto.getCityId(), null)); + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/services/exceptions/DatabaseException.java b/src/main/java/com/devsuperior/bds02/services/exceptions/DatabaseException.java new file mode 100644 index 00000000..af9e5c31 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/services/exceptions/DatabaseException.java @@ -0,0 +1,10 @@ +package com.devsuperior.bds02.services.exceptions; + +public class DatabaseException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public DatabaseException(String msg) { + super(msg); + } +} \ No newline at end of file diff --git a/src/main/java/com/devsuperior/bds02/services/exceptions/ResourceNotFoundException.java b/src/main/java/com/devsuperior/bds02/services/exceptions/ResourceNotFoundException.java new file mode 100644 index 00000000..bee700d8 --- /dev/null +++ b/src/main/java/com/devsuperior/bds02/services/exceptions/ResourceNotFoundException.java @@ -0,0 +1,10 @@ +package com.devsuperior.bds02.services.exceptions; + +public class ResourceNotFoundException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ResourceNotFoundException(String msg) { + super(msg); + } +} \ No newline at end of file