TheStranger
TheStranger

Reputation: 1597

How do i differentiate between two endpoints, each with one PathVariable?

I'm working on a Spring Boot application. I have the following REST endpoint(s):

 @GetMapping(value = { "/person/{name}", "/person/{age}" })
 public PersonData getPersonData(@PathVariable(required = false) String name,
                                 @PathVariable(required = false) Integer age) {

}

This endpoint can be called with either a name variable or an age variable, however it looks like it can't differentiate between them. If I was to call '.../person/20', it would not call "/person/{age}", but it always calls "/person/{name}".

I know I could make something like:

@GetMapping(value = { "/person/name/{name}", "/person/age/{age}" })

However are there any other way to solve it without adding anything to the path?

Upvotes: 3

Views: 1482

Answers (3)

Simon Martinelli
Simon Martinelli

Reputation: 36223

A path variable is something like a primary key usually.

Like:

/person/{id}

What you try is to search for data and this should be done with query parameters.

Example:

@GetMapping(value = { "/person/{name}", "/person/{age}" })
public PersonData getPersonData(@RequestParam String name,
                                @RequestParam Integer age) {

}

Then you can call it

/person?age=40
/person?name=Peter

Upvotes: 6

Panagiotis Bougioukos
Panagiotis Bougioukos

Reputation: 19183

In your case I would make 2 different endpoints to be more clear, each one requiring it's own query parameter to be served.

 @GetMapping(value = "/person")
 public PersonData getPersonDataByName(@RequestParam(required = true) String name) {
 ....
}


 @GetMapping(value = "/person")
     public PersonData getPersonDataByAge(@RequestParam(required = true) Integer age) {
 ....   
    }

required = true can be omitted from the annotation as this is the default value, I used it just to point that each endpoint will be fulfilled only for that specific query parameter

Upvotes: 2

Ajit Singh
Ajit Singh

Reputation: 102

age and name are logically not the same thing; the chosen best answer correctly suggests to keep them as distinguished parameters.

However you can check if the value is numeric and treat it like an age,

@GetMapping("/person/{value}")
public String getPerson(@PathVariable String value) {
    if (value.matches("[0-9]|[0-9][0-9]"))
        return "Age";
    else
        return "Name";
}

but this is ambiguous and error prone (e.g. how'll you distinguish when adding other numerical params like shoeSize or numberOfPartners?).

Upvotes: 2

Related Questions