Reputation: 465
When creating my rest application, I had a big problem. It lies in the nesting of elements and my misunderstanding of how to properly give them through the rest controller. I have something like the following structure:
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
@JsonManagedReference
private List<TaskCard> taskCards;
}
public class TaskCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "taskCard", fetch = FetchType.LAZY)
@JsonManagedReference
private List<Task> tasks;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
@JsonBackReference
private User user;
}
public class Task {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "task_card_id")
@JsonBackReference
private TaskCard taskCard;
}
All these classes are entities. As you might have guessed, I have a rest controller for each of these classes. This is where the problems begin. In my head, the structure of my rest api should look something like this: /users/1/taskkards/1/tasks/1/
. It looks complicated, right? Exactly! When I try to just get the user, then there are no problems in the principe, I can just send a /users
request that my user rest controller will process. But if we go down to taskcard, then there are already problems. It turns out that my TaskCardController should look like this:
@RestController
@RequestMapping("users/{userId}/taskcards")
public class TaskCardController {
// get, post, update, delete methods
}
This already means that I must also transfer the user info here to make sure that the task card belongs to him. But at the same time, because my user has a task cards field, where can I get this value from? Do I need to go to the repository and look for it in the database, or just do something like that?
@GetMapping
public List<TaskCard> getAllTaskCards(@PathVariable("userId") User user) {
return user.getTaskCards();
}
Is it normal at all that such nesting arises? Why then do I need to create controllers for taskCard and task, if I can just get them from user? This is also one of the problems.If we go down even further to the task, then here everything is very bad. My task controller should look like this?
@RestController
@RequestMapping("users/{userId}/taskcards/{cardId}/tasks")
public class TaskController {
// get, post, update, delete methods
}
Something tells me no. This will be terrible if I have to get a user and a task card to request a task. What should I do in this situation? How do I design my rest API correctly?
Upvotes: 3
Views: 144
Reputation: 871
For the Task and TaskCard controllers just send the JSON from the client and then fetch the corresponding User from the database. For example,
@RestController
@RequestMapping("/taskcards")
public class TaskCardController {
@Autowired
private UserRepo userRepo; // supposing you are using Spring Data repositories
@PostMapping("/addTaskCard")
public ResponseEntity addTaskCard(@RequestBody TaskCard newTaskCard){
User user = userRepo.getUserById(newTaskCard.getUser().getId());
user.getTaskCards().add(newTaskCard);
userRepo.save(user);
return ResponseEntity.ok().build();
}
}
You can continue using this method. Send just enough data from the client and then in the backend do your queries and get the other related entities from the databse.
Upvotes: 1