I’m newbie with java. I tried to implement update method for my API. I want to update some field of my data. Here is my data class:
public class Task implements Serializable { @Id private String id; private String task; private Boolean isCompleted; private String userId; }
My service interface:
public interface TaskService { void create(Task task); Mono<Task> findById(String id); Flux<Task> findAll(); Mono<Task> update(String Id, Task task); Mono<Void> delete(String id); }
And implement for services:
@Service public class TaskServiceImpl implements TaskService { @Autowired TaskRepository taskRepository; public void create(Task task) { taskRepository.save(task).subscribe(); } public Mono<Task> findById(String Id) { return taskRepository.findById(Id); } public Flux<Task> findAll() { return taskRepository.findAll(); } public Mono<Task> update(String Id, Task task) { // System.out.println(taskRepository.findById(Id)); return taskRepository.findById(Id) .switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND"))) .map(b -> { task.setId(Id); if (task.getTask() != null) task.setTask(task.getTask()); if (task.getIsCompleted() != null) task.setIsCompleted(task.getIsCompleted()); if (task.getUserId() != null) task.setUserId(task.getUserId()); return task; }) .flatMap(taskRepository::save); } public Mono<Void> delete(String id) { return taskRepository.deleteById(id); } }
My Controller:
@RestController public class TaskController { @Autowired private TaskService taskService; @PostMapping("/tasks") @ResponseStatus(HttpStatus.CREATED) public void create(@RequestBody Task task) { taskService.create(task); } @GetMapping("/tasks/{id}") public ResponseEntity<Mono<Task>> findbyId(@PathVariable("id") String Id) { Mono<Task> task = taskService.findById(Id); return new ResponseEntity<Mono<Task>>(task, task != null ? HttpStatus.OK : HttpStatus.NOT_FOUND); } @GetMapping(value = "/tasks") @ResponseBody public Flux<Task> findAll() { return taskService.findAll(); } @PutMapping("/tasks/{id}") @ResponseStatus(HttpStatus.OK) public Mono<Task> update(@PathVariable("id") String Id, @RequestBody Task task) { return taskService.update(Id, task); } @DeleteMapping("/tasks/{id}") @ResponseStatus(HttpStatus.OK) public void delete(@PathVariable("id") String id) { taskService.delete(id).subscribe(); } }
And Task Repository:
@Repository public interface TaskRepository extends ReactiveMongoRepository<Task, String> { }
My data in DB:
{ "id": "2", "task": "do", "isCompleted": true, "userId": "1" }
My request body:
{ "userId": "2", "task": "updated" } }
I expected:
{ "id": "2", "task": "updated", "isCompleted": true, "userId": "2" }
But it responsed:
{ "id": "2", "task": "updated", "isCompleted": null, "userId": "2" }
It update my missing value in request with null value. How can I update specific values in data?
Advertisement
Answer
The problem is here:
return taskRepository.findById(Id) .switchIfEmpty(Mono.error(new Exception("TASK_NOT_FOUND"))) .map(b -> { task.setId(Id); if (task.getTask() != null) task.setTask(task.getTask()); if (task.getIsCompleted() != null) task.setIsCompleted(task.getIsCompleted()); if (task.getUserId() != null) task.setUserId(task.getUserId()); return task; })
You completely ignore the fetched Task
(b
instance) and update the task
with its own values. You probably need something like this:
.map(fetchedTask -> { if (task.getTask() != null) { fetchedTask.setTask(task.getTask()); } return fetchedTask; })