Im struggling on how to implement a API when the methods in my controller are returning a ModelAndView. Most tutorials I can find are returning ResponseEntities. Should i be making seperate API controllers which strictly handle the API calls under a /api mapping? (which i believe isn't RESTFUL practice). Or is it possible to handle my API calls in the same controller, even when making use of ModelAndView?
My controller looks as following:
@RestController
@RequestMapping("/dish")
public class DishController {
private final DishRepository dishRepository;
public DishController(DishRepository dishRepository) {
this.dishRepository = dishRepository;
}
@GetMapping
public ModelAndView list() {
Iterable<Dish> dishes = this.dishRepository.findAll();
return new ModelAndView("dishes/list", "dishes", dishes);
}
@GetMapping("{id}")
public ModelAndView view(@PathVariable("id") Dish dish) {
return new ModelAndView("dishes/view", "dish", dish);
}
@GetMapping(params = "form")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String createForm(@ModelAttribute Dish dish) {
return "dishes/form";
}
@ResponseStatus(HttpStatus.CREATED)
@PostMapping
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ModelAndView create(@Valid Dish dish, BindingResult result,
RedirectAttributes redirect) {
if (result.hasErrors()) {
return new ModelAndView("dishes/form", "formErrors", result.getAllErrors());
}
dish = this.dishRepository.save(dish);
redirect.addFlashAttribute("globalMessage", "view.success");
return new ModelAndView("redirect:/d/{dish.id}", "dish.id", dish.getId());
}
@RequestMapping("foo")
public String foo() {
throw new RuntimeException("Expected exception in controller");
}
@ResponseStatus(HttpStatus.OK)
@GetMapping("delete/{id}")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ModelAndView delete(@PathVariable("id") Long id) {
this.dishRepository.deleteById(id);
Iterable<Dish> dishes = this.dishRepository.findAll();
return new ModelAndView("dishes/list", "dishes", dishes);
}
@ResponseStatus(HttpStatus.OK)
@GetMapping("/modify/{id}")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public ModelAndView modifyForm(@PathVariable("id") Dish dish) {
return new ModelAndView("dishes/form", "dish", dish);
}
@RestController is a shorthand for writing @Controller and @ResponseBody, which you should only use if all methods are returning an object that should be treated as the response body (eg. JSON).
If you want to combine both REST endpoints and MVC endpoints within the same controller, you can annotate it with @Controller and individually annotate each method with @ResponseBody.
For example:
@Controller // Use @Controller in stead of @RestController
@RequestMapping("/dish")
public class DishController {
@GetMapping("/list")
public ModelAndView list() { /* ... */ }
@GetMapping
@ResponseBody // Use @ResponseBody for REST API methods
public List<Dish> findAll() { /* ... */ }
}
Alternatively, as you've mentioned, you can use multiple controllers:
@Controller
@RequestMapping("/dish")
public class DishViewController { /* ... */ }
@RestController
@RequestMapping("/api/dish")
public class DishAPIController { /* ... */ }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With