简体   繁体   中英

Spring Boot REST - Ambiguous mapping even with unique path variables

I have two endpoints with a different set of path variables. They both work unless I give an optional parameter (name) in the URL. Then Spring gives ambiguous error.

The optional parameter name is also present in the second endpoint which is why the error happens.

Why does Spring think these endpoints are ambiguous?

Required parameters should make the endpoints unique (because first endpoint contains parameter "sourceid" and the second one does not). The following URL gives the error:

/?sourceid=999&applicantid=1&startingdate=2020&endingdate=2021& name=mobileapp

First Endpoint:

@GetMapping(value = "/", params= {"sourceid", "applicantid", "startingdate", "endingdate"})
public List<Event> getEventsById(
        @RequestParam("sourceid") String sourceid,
        @RequestParam("applicantid") String applicantid,
        @RequestParam("startingdate") String startingdate,
        @RequestParam("endingdate") String endingdate,
        @RequestParam(value = "name", required = false) String name) {

Second Endpoint:

@GetMapping(value = "/", params= { "name", "applicantid", "startingdate", "endingdate"})
public List<Event> getEventsByApplicantId(
        @RequestParam("applicantid") String applicantid,
        @RequestParam("name") String name,
        @RequestParam("startingdate") String startingdate,
        @RequestParam("endingdate") String endingdate) {

Error Message:

java.lang.IllegalStateException: Ambiguous handler methods mapped for '/event-example/': {public java.util.List com.eventrest.controller.MyController.getEventsById(java.lang.String,java.lang.String,java.lang.String,java.lang.String) throws java.text.ParseException, public java.util.List com.eventrest.controller.MyController.getEventsByApplicantId(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) throws java.text.ParseException}
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:413) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:367) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:110) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getHandlerInternal(RequestMappingInfoHandlerMapping.java:59) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:396) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1234) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1016) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.38.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.38.jar:4.0.FR]

Spring can't distinguish if the request GET http://localhost:8080/?sourceid=999&applicantid=1&startingdate=2020&endingdate=2021&name=mobileapp will be handled by getEventsById() or by getEventsByApplicantId() because your mapping is ambiguous.

Consider that the sourceid is required = false in the second method as in the first method , naturally these two methods are the same.

There is a way out of ambiguous.

You can narrow request mappings based on request parameter conditions. You can test for the presence of a request parameter (myParam), for the absence of one (,myParam). or for a specific value (myParam=myValue). Read Reference

Add !sourceid to the params field in your getEventsByApplicantId() method as follows:

@GetMapping(value = "/", params= {"!sourceid", "name", "applicantid", "startingdate", "endingdate"})
public List<Event> getEventsByApplicantId(
        @RequestParam("applicantid") String applicantid,
        @RequestParam("name") String name,
        @RequestParam("startingdate") String startingdate,
        @RequestParam("endingdate") String endingdate) {
    // ..
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM