0

I know the difference between @PathVariable and @RequestParam, that's not the point.

I have also read some articles but I still don't understand when to use one or the other in a simple case.

For a REST API, let's say I have a User entity with id and username (both are unique).

Now I want to get a user by username.

I have 2 options :

@GetMapping(path = "/users/{username}")
public ResponseEntity<Object> getUser(@PathVariable String username){
    //Get user
}

or

@GetMapping(path = "/users}")
public ResponseEntity<Object> getUser(@RequestParam String username){
    //Get user
}

Which one do I have to use (@RequestParam is not mandatory in the code, I placed it just to be clearer) ?

Thanks

Manta
  • 490
  • 5
  • 18
  • It's entirely up to you but a typical REST API will use IDs in the path so I would go for option #2 personally (without the trailing `/` on `/users/`), eg `/users?username=whatever` – Phil May 28 '20 at 23:47
  • 1
    It is a design choice. if you want to access the URL like this "/users/john" you use path variable, but with request param, "/users?username=john". possible duplicate : https://stackoverflow.com/questions/37878684/when-to-choose-requestparam-over-pathvariable-and-vice-versa – Lyju I Edwinson May 28 '20 at 23:50
  • Thanks, I edited for the `/` – Manta May 28 '20 at 23:50
  • I saw the possible duplicated question but I don't really have my answer, for me it's not clear... – Manta May 28 '20 at 23:52
  • The issue with mixing path variables is being able to tell the difference between `/users/{username}` and `/users/{id}`. You can use a [regular expression](https://stackoverflow.com/questions/20527321/what-is-the-meaning-of-id-in-a-spring-mvc-requestmapping-handler-method) in the request mapping but that really depends on the data type of your `id` – Phil May 28 '20 at 23:53
  • 1
    Note: It's best, when practical, to return `ResponseEntity` (or just return the result type and dispense with the `ResponseEntity` unless you need to set headers). – chrylis -cautiouslyoptimistic- May 28 '20 at 23:56
  • Thanks for that. The reason is that at the beginning it asked me for a type and I saw somewhere ``. As it works, I left like that :-). But totally agree, it's ok with the returned type. – Manta May 29 '20 at 00:02

1 Answers1

3

The path part of a URL identifies a resource, and a query string represents a query. While a query can certainly return exactly one item, a collection-resource URL (/users) should return an array of items (from zero to infinity), while a record-resource URL (/users/123) should return exactly one item (and this is the URL that should handle DELETE/PUT requests).

If the username is actually the canonical ID for the user, it should be a path variable; if there is a different canonical ID (such as a UUID), but you're searching by username, then use a query parameter but return a collection of zero or one results. (You can use params=username in the request mapping to only match the controller when that query parameter is present.)

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • Ok, so maybe if I have the id and I want to know for exemple the email, let's go with path variable. If I want to look for a user with a username, let's go with param. Would it be a solution? – Manta May 28 '20 at 23:58
  • 1
    @Manta Presuming that the username is different from the ID (which is a good practice, so that you can change the username), then that's exactly how to do it. You'll usually want to limit the request mapping with `params` in that case. – chrylis -cautiouslyoptimistic- May 28 '20 at 23:59
  • 1
    Always use `id` even if `username` is unique, I think it's better in term of performance, memory usage, editable capabilities, joining, etc...Finally I understood, thanks for all. – Manta May 29 '20 at 00:06