Skip to content

Commit 86ce89d

Browse files
committed
add a GlobalExceptionHandler and TaskNotFoundException
1 parent 391d0fa commit 86ce89d

4 files changed

Lines changed: 63 additions & 58 deletions

File tree

src/main/java/com/taskmanagerapi/controller/TaskController.java

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,10 @@ public TaskController(TaskService taskService) {
2020

2121
@PostMapping("/tasks")
2222
public ResponseEntity<Task> addTask(@RequestBody Map<String, String> request) {
23-
try {
24-
String name = request.get("name");
25-
String description = request.get("description");
23+
String name = request.get("name");
24+
String description = request.get("description");
2625

27-
Task task = taskService.addTask(name, description);
28-
return ResponseEntity.ok(task);
29-
} catch (IllegalArgumentException e) {
30-
return ResponseEntity.badRequest().build();
31-
}
26+
return ResponseEntity.ok(taskService.addTask(name, description));
3227
}
3328

3429
@GetMapping("/tasks")
@@ -38,42 +33,31 @@ public ResponseEntity<List<Task>> getAllTasks() {
3833

3934
@GetMapping("/tasks/{id}")
4035
public ResponseEntity<Task> getTask(@PathVariable String id) {
41-
return taskService.getTask(id)
42-
.map(ResponseEntity::ok)
43-
.orElse(ResponseEntity.notFound().build());
36+
return ResponseEntity.ok(taskService.getTask(id));
4437
}
4538

4639
@GetMapping("/tasks/search/{name}")
4740
public ResponseEntity<Task> searchTaskByName(@PathVariable String name) {
48-
return taskService.searchTaskByName(name)
49-
.map(ResponseEntity::ok)
50-
.orElse(ResponseEntity.notFound().build());
41+
return ResponseEntity.ok(taskService.searchTaskByName(name));
5142
}
5243

5344
@GetMapping("/tasks/search/status/{status}")
5445
public ResponseEntity<List<Task>> searchTaskByStatus(@PathVariable TaskStatus status) {
55-
List<Task> tasks = taskService.searchTaskByStatus(status);
56-
return ResponseEntity.ok(tasks);
46+
return ResponseEntity.ok(taskService.searchTaskByStatus(status));
5747
}
5848

5949
@PatchMapping("/tasks/{id}/complete")
6050
public ResponseEntity<Task> completeTask(@PathVariable String id) {
61-
return taskService.completeTask(id)
62-
.map(ResponseEntity::ok)
63-
.orElse(ResponseEntity.notFound().build());
51+
return ResponseEntity.ok(taskService.completeTask(id));
6452
}
6553

6654
@DeleteMapping("/tasks/{id}")
6755
public ResponseEntity<Task> deleteTask(@PathVariable String id) {
68-
return taskService.deleteTask(id)
69-
.map(ResponseEntity::ok)
70-
.orElse(ResponseEntity.notFound().build());
56+
return ResponseEntity.ok(taskService.deleteTask(id));
7157
}
7258

7359
@PatchMapping("/tasks/{id}")
7460
public ResponseEntity<Task> undoDelete(@PathVariable String id) {
75-
return taskService.undoDelete(id)
76-
.map(ResponseEntity::ok)
77-
.orElse(ResponseEntity.notFound().build());
61+
return ResponseEntity.ok(taskService.undoDelete(id));
7862
}
7963
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.taskmanagerapi.exception;
2+
3+
import org.springframework.http.HttpStatus;
4+
import org.springframework.http.ResponseEntity;
5+
import org.springframework.web.bind.annotation.ExceptionHandler;
6+
import org.springframework.web.bind.annotation.RestControllerAdvice;
7+
8+
import java.time.LocalDateTime;
9+
import java.time.temporal.ChronoUnit;
10+
import java.util.Map;
11+
12+
@RestControllerAdvice
13+
public class GlobalExceptionHandler {
14+
15+
@ExceptionHandler(TaskNotFoundException.class)
16+
public ResponseEntity<Map<String, Object>> handleTaskNotFound(TaskNotFoundException ex) {
17+
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of(
18+
"error", ex.getMessage(),
19+
"status", 404,
20+
"timestamp", LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)
21+
));
22+
}
23+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.taskmanagerapi.exception;
2+
3+
public class TaskNotFoundException extends RuntimeException {
4+
5+
public TaskNotFoundException(String id) {
6+
super("Task not found: " + id);
7+
}
8+
}
Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
package com.taskmanagerapi.service;
22

3+
import com.taskmanagerapi.exception.TaskNotFoundException;
34
import com.taskmanagerapi.model.Task;
45
import com.taskmanagerapi.model.TaskStatus;
56
import com.taskmanagerapi.repository.TaskRepository;
6-
import org.slf4j.Logger;
7-
import org.slf4j.LoggerFactory;
87
import org.springframework.stereotype.Service;
98
import org.springframework.transaction.annotation.Transactional;
109

1110
import java.util.List;
12-
import java.util.Optional;
1311

1412
import static com.taskmanagerapi.model.TaskStatus.*;
1513

1614
@Service
1715
public class TaskService {
18-
private static final Logger logger = LoggerFactory.getLogger(TaskService.class);
1916

2017
private final TaskRepository taskRepository;
2118

@@ -32,49 +29,42 @@ public List<Task> getAllTasks() {
3229
return taskRepository.findAll();
3330
}
3431

35-
public Optional<Task> getTask(String id) {
36-
return taskRepository.findById(id);
32+
public Task getTask(String id) {
33+
return taskRepository.findById(id)
34+
.orElseThrow(() -> new TaskNotFoundException(id));
3735
}
3836

39-
public Optional<Task> searchTaskByName(String name) {
40-
return taskRepository.findTaskByName(name);
37+
public Task searchTaskByName(String name) {
38+
return taskRepository.findTaskByName(name)
39+
.orElseThrow(() -> new TaskNotFoundException(name));
4140
}
4241

4342
public List<Task> searchTaskByStatus(TaskStatus status) {
4443
return taskRepository.findTasksByStatus(status);
4544
}
4645

4746
@Transactional
48-
public Optional<Task> completeTask(String id) {
49-
return taskRepository.findById(id).map(task -> {
50-
task.setStatus(DONE);
51-
return task;
52-
});
47+
public Task completeTask(String id) {
48+
Task task = taskRepository.findById(id)
49+
.orElseThrow(() -> new TaskNotFoundException(id));
50+
task.setStatus(DONE);
51+
return task;
5352
}
5453

5554
@Transactional
56-
public Optional<Task> deleteTask(String id) {
57-
return taskRepository.findById(id).map(task -> {
58-
if (task.getStatus() == DELETED) {
59-
logger.info("Task '{}' is already deleted", task.getName());
60-
} else {
61-
task.setStatus(DELETED); // soft delete
62-
logger.info("Task '{}' has been deleted", task.getName());
63-
}
64-
return task;
65-
});
55+
public Task deleteTask(String id) {
56+
Task task = taskRepository.findById(id)
57+
.orElseThrow(() -> new TaskNotFoundException(id));
58+
task.setStatus(DELETED);
59+
return task;
6660
}
6761

6862
@Transactional
69-
public Optional<Task> undoDelete(String id) {
70-
return taskRepository.findById(id).map(task -> {
71-
if (task.getStatus() == DELETED) {
72-
task.setStatus(CREATED);
73-
logger.info("Task '{}' reactivated", task.getName());
74-
} else {
75-
logger.info("Task '{}' could not be reactivated", task.getName());
76-
}
77-
return task;
78-
});
63+
public Task undoDelete(String id) {
64+
Task task = taskRepository.findById(id)
65+
.orElseThrow(() -> new TaskNotFoundException(id));
66+
67+
task.setStatus(CREATED);
68+
return task;
7969
}
8070
}

0 commit comments

Comments
 (0)