Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two GET methods with different number of query parameters : REST

I have an Rest endpoint class as below :

@Path("/sports")
public interface SportsEndpoint {

    @GET
    List<Player> getPlayersOfSports(@QueryParam("sportId") String sportId, @QueryParam("sportName") String sportName);


    @GET
    List<Player> getPlayersOfSports(@QueryParam("sportId") String sportId, @QueryParam("sportName") String sportName, @QueryParam("country") String country);

}

As you can see, I have two GET methods which has almost the same signature except the second method takes an additional QueryParam.

I try to access these endpoints using the urls:

http://localhost:8080/rest/api/sports?sportId=100&sportName=badminton http://localhost:8080/rest/api/sports?sportId=100&sportName=badminton&country=japan

Both these urls are resolving to use the first method signature. Ideally, I was expecting that for the first url, the first method signature would be called and for the second url the second method(the one with 3 query parameters) would have been called.
But looks like in both cases the first method is getting called.

I know that Rest resources are uniquely identified by the path and not the query parameters. But is it also true that even though the number of query parameters are different, the rest endpoint will not be uniquely identified ?
Can someone point me to some specifications/articles/documentation where I can understand polymorphism when it comes to designing rest api endpoints ?

FYI: I am using RestEasy.

like image 754
RITZ XAVI Avatar asked Mar 10 '23 17:03

RITZ XAVI


2 Answers

Java rest APIs are implementation of Jax-Rs as far as i know, so you can read Jax-Rs specification ,

Jax-Rs maps Path to Resource method. Resource methods must have a unique path. Query params are not considered part of the path. Resource methods are methods of a resource class annotated with a request method designator. It is not determined by the specs what should happen when two methods share the same designator and path, but most implementation will use only one of them and will not report error.

(Conforms with the URL specs. )

This means that you cannot use overloading.

Inheritance is allowed. From the Jax-Rs spec:

JAX-RS annotations MAY be used on the methods and method parameters of a super-class or an implemented interface. Such annotations are inherited by a corresponding sub-class or implementation class method provided that method and its parameters do not have any JAX-RS annotations of its own. Annotations on a super-class take precedence over those on an implemented interface. If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the super class or interface method are ignored. E.g.:

like image 157
Martin Hlavňa Avatar answered Mar 22 '23 23:03

Martin Hlavňa


QueryParams are the optional params as

you correctly stated I know that Rest resources are uniquely identified by the path and not the query params

and to answer your question ,

yes even though the number of query parameters are different, the rest endpoint will not be uniquely identified ? as it is identified by the path not the query params.

If you want that your methods should be called based on the no of inputs in your querystring it is better to create a single method, which takes all the queryparam according to your requirement and based on the no of inputs provided, you call each methods separately.

So in your case, it can be rewritten as below :-

@Path("/sports")
public class SportsEndpoint {
        
    @GET
    List<Player> getPlayers(@QueryParam("sportId") String sportId, 
                            @QueryParam("sportName") String sportName,
                            @QueryParam("country") String country){
        if(sportId != null && sportName != null) {
            getPlayersOfSports(sportId,sportName);
        } else if (sportId != null && sportName != null && country != null) {
            getPlayersOfSports(sportId,sportName,country);
        }
    }
}

And

then you define the method overloading in your business logic, which will have 2 overloaded methods, which varies based on no of arguments. This way you can achieve polymorphism.

like image 26
Amit Avatar answered Mar 22 '23 22:03

Amit