furry12
furry12

Reputation: 962

Spring REST endpoint with varying query parameter type

I was wondering about how to implement a REST endpoint in Spring Boot so that it will return a list of objects based on two criteria, which will be lists of values or the word "ALL".

For example: I want to retrieve a list of users that come from any of given countries (I want to provide a list of String typed country codes as a query param) AND that are part of any of given groups (I provide a list of Long typed ids of groups). That would look kind of like this:

 @GetMapping("users")
public List<UserDto> findUsers(
        @RequestParam("countries") List<String> countryCodes,
        @RequestParam("groupIds") List<Long> groupsIds) {
    return matchingService.findMatchingUsersBy(groupIds, countryCodes);
}

Then my request would look like for example:

/v1/users?countries=US,UK,GE&groupIds=1,4,5,6

Now, what if I am expected to make it work when one or both parameters are 'ALL' as well, like this:

/v1/users?countries=ALL&groupIds=ALL 
/v1/users?countries=UK,FR&groupIds=ALL
/v1/users?countries=ALL&groupIds=1,2,3

The expectation here is that the application will fetch all possible values from the DB and search based on that.

I am pretty sure that I would get an exception saying that "ALL" is not a valid Long value for List groupIds.

Is there a way to provide different implementation for the same endpoint based on different Query Parameter type? What is the cleanest way to do it?

Upvotes: 1

Views: 1765

Answers (2)

Safwan Shaikh
Safwan Shaikh

Reputation: 546

When you want to retrieve data on the basis of specific country codes and group ids, no need to pass any thing just need to make requestParams optional and handle this on code.

 @GetMapping("users")
 public List<UserDto> findUsers(
    @RequestParam("countries", required = false) List<String> countryCodes,
    @RequestParam("groupIds", required = false) List<Long> groupsIds) {
if(countryCodes == null){
    countryCodes = fetchCountryCodeFromRepo();
}
if(groupIds == null){
    groupIds = fetchGroupIdsFromRepo();
}
return matchingService.findMatchingUsersBy(groupIds, countryCodes);
}

Upvotes: 2

Spasoje Petronijević
Spasoje Petronijević

Reputation: 1598

Simplest solution will be to pass String ALL and than first line in your Controller should be:

List<String> countries;
if(countryCodes.contains("ALL")) {
  List<String> countries = countryRepository.findAll();
} else {
  countries = countryCodes;
}
matchingService.findMatchingUsersBy(groupIds, countries);

Also, you can make @RequestParam(required = false) so if you receive null instead of groupIds you know that you should include all groups. But this is also so much customization. Client of this API will not be sure if sending nothing to api means "all groups" of "none of the groups". It have to be documented very well if you go with "ALL" solution or "not required" solution. If your use case allows it, cleanest way is to send 100 Strings in list of countries or groups if required.

Upvotes: 0

Related Questions