4

I am trying to build a REST application in Spring where I have a requirement to delete resources on the basis of certain path variables.

For example, I want to delete resource(s) by id

@DeleteMapping("resources/{id}")

or by name

@DeleteMapping("resources/{name}")

But when I do the above, I get the error

java.lang.IllegalStateException: Ambiguous handler methods

As I understand, Servlets can't tell whether 123 in path /resources/123 represents an ID or a name and hence the ambiguity.

How shall then I design my REST endpoint where a DELETE happens based on some parameter or maybe a combination of parameters?

Auro
  • 1,578
  • 3
  • 31
  • 62

3 Answers3

3

Spring can't distinguish between the two request as your mapping is ambiguous.

You could try using a query parameter for the second request. So it could look like following :

 @DeleteMapping("/hello/{id}")
 public String deleteById(@PathVariable("id") Long id) {
    return "Delete by id called";
 }


  @DeleteMapping("/hello")
  public String deleteByName(@RequestParam(value = "name") String name) {
    return "Delete by name called";
  }

Requests like DELETE http://localhost:8080/hello/1 will be handled by deleteById

Requests like DELETE http://localhost:8080/hello?name=deleteMe will be handled by deleteByName.

Or you could add name query param to the same method and if your query param is not null you could delete by name.

Swapnil Khante
  • 547
  • 2
  • 10
1

For delete by id mapping is fine using path variable

@DeleteMapping("resources/{id}")

For delete by name you can take name as a query param

@DeleteMapping("resources")
public ResponseEntity<?> delete(@RequestParam(value = "name") String name) {

Or you can take both id and name as query param if you want to map both operations in one method in the controller.

Eklavya
  • 17,618
  • 4
  • 28
  • 57
0

Seems like you have two options:

  1. Use only one mapping and disambiguate the request in your controller code. For example, try to parse the path param as an integer or match it to some pattern.
  2. Use regex in the path pattern like @DeleteMapping("resources/{id:[0-9]+}") See Spring Docs - Request Mapping URI Patterns for details. This assumes you can tell the difference between an ID and a name with a pattern though.
takteek
  • 7,020
  • 2
  • 39
  • 70
  • What @Eklavya said is potentially better since then you don't have 2 URLs for the same resource. Delete by name is more a find+delete operation. – takteek Jul 11 '20 at 19:04