Home > Enterprise >  How to handle Ambiguous handler methods mapped in REST application with Spring
How to handle Ambiguous handler methods mapped in REST application with Spring

Time:07-03

In my UserController, I have 3 @GetMapping methods:

getAllUsers() - It is used to get all users, getUserById() - It is used to get specific user with his unique id and getUserByName() - It is used to get specific user with his unique name.

The code from the method is as follows:

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserRepository userRepository;

    @Autowired
    public UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }


    @GetMapping
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }


    @GetMapping(value = "/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userRepository.findById(id);
        return ResponseEntity.ok(user);
    }


    @GetMapping(value = "/{name}")
    public ResponseEntity<User> getUserByName(@PathVariable String name) {
        User user = userRepository.findUserByName(name);
        return ResponseEntity.ok(user);
    }

The first problem is that my app doesn't know if the URL is String or Integer, so I solved the problem between the getUserById() and getUserByName() methods like this:

    @GetMapping(value = "{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userRepository.findById(id);
        return ResponseEntity.ok(user);
    }


    @GetMapping
    public ResponseEntity<User> getUserByName(@RequestParam(value = "name") String name) {
        User user = userRepository.findUserByName(name);
        return ResponseEntity.ok(user);
    }

So now I can access the methods with:

http://localhost:8080/users/1 and http://localhost:8080/users?name=john

When I run the application, I get this error:

Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'userController' method 
com.db.userapp.controller.UserController#getUserByName(String)
to {GET [/users]}: There is already 'userController' bean method

I believe this is because my getAllUsers() and getUserByName() methods are on the same URL format. Does anyone have an idea how I can solve this?

CodePudding user response:

You're right. You have defined two GET Methods on /users and therefore its basically the same as your first problem.

You can merge these methods and set the RequestParam for name as not required and just use it when it's not null. The problem here is that you would return one User as List even though you know that there is only one User for this name. Which I think is fine because its not the Users main identifier and with the RequestParam it's more like a filter anyway.

CodePudding user response:

You are right because both getAllUsers() and getUserByName() are mapped to the /users/. So for the request /users/ , it does not know which method should be used to process it.

You can configure the name query parameter for /users/ as optional and check if its value is null. Null means user does not want have any filtering on the users and want to get all users :

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping
    public List<User> getUser(@RequestParam(value = "name",required = false) String name) {

        if (Strings.isNullOrEmpty(name)) {
            return userRepository.findAll();
        } else {
            return userRepository.findUserByName(name);
        }
    }
}
  • Related