vtomic85 vtomic85 - 9 days ago 6
reST (reStructuredText) Question

Spring REST controller with different functions

I have a Spring

@RestController
for manipulating my Users and I want to have several functions:



  • /users : GET (returns all users)

  • /users/:id : GET (returns a user with given ID, default id=1)

  • /users : POST (inserts a user)

  • /users/:id : DELETE (deletes a user with given ID)



I started working on it but I'm not sure how to manage the "overlapping" URIs for the same method (e.g. first two cases). Here's what I came with so far:


@RestController
public class UserController {
@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getAllUsers() {
return UserDAO.getAll();
}

@RequestMapping(value = "/users", method = RequestMethod.GET)
public User getUser(@RequestParam(value = "id", defaultValue = "1") int id) {
return UserDAO.getById(id);
}
}


This won't work due to "ambiguous mapping" and it's pretty clear to me, but I don't know what to do. Should I change one of the URIs or there is some other way?

Edit:
I've also tried changing the second method to:

@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public User getUser(@PathVariable("id") int id) {
return UserDAO.getById(id);
}


Still doesn't work.

Answer

Your current mapping:

@RequestMapping(value = "/users", method = RequestMethod.GET)
public User getUser(@RequestParam(defaultValue = "1") int id)

Would map to the /users?id=42 not the desired /users/42. If you want to create a mapping for /users/:id endpoint, use the following:

@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
public User getUser(@PathVariable int id) {
    return UserDAO.getById(id);
}

Also, as of Spring Framework 4.3, you can use new meta annotations to handle GET, POST, etc. methods:

@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping
    public List<User> getAllUsers() {
        return UserDAO.getAll();
    }

    @GetMapping("{id}")
    public User getUser(@PathVariable int id) {
        return UserDAO.getById(id);
    }
}