4

I have a Spring application where I declared my class like so:

@Controller
@RequestMapping(value = "/rest/api/datasources/", produces = MediaType.APPLICATION_JSON_VALUE, method=RequestMethod.GET)
public class MetadataServiceController {
    //Two separate methods:
    @RequestMapping(value="{datasourceName}")
    public Object getLatestApiMetadata(@PathVariable String datasource, 
           @RequestParam (required = false)  String datasourceNum,
           @RequestParam (defaultValue = "true")  String dataFields, 
           @RequestParam ( required=false, defaultValue = "api")  String visibility){
      ... //Implementation here
    }

    @RequestMapping(value="{apiVersion}")
    public @ResponseBody List<DataSource> getAllMetadata(
        @RequestHeader(value="sub-version", required=false, defaultValue="0.0") String minorVer,
        @PathVariable String restApiVersion,
        @RequestParam(required = false) String datasourceNum,
        @RequestParam(defaultValue = "all") String visibility)
        throws ObjectNotFoundException {
    ... //Implementation here
    }

}

But when I try to reach one of these rest endpoints, I get an error saying: java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path and it specifies those two methods as the issue. I was under the impression that if I change the request parameters, Spring would not complain about them being the same via this post: http://www.coderanch.com/t/598675/Spring/handling-HTTP-Request-parameters but clearly it still does. Would anyone have any suggestions on how to get around this? Thanks!

user1871869
  • 3,317
  • 13
  • 56
  • 106
  • If I send a request to `http://your.server/rest/api/datasources/foo`, which method should be called? How about `http://your.server/rest/api/datasources/bar`? – Boris the Spider Sep 29 '15 at 07:25
  • @BoristheSpider ah yes, but didn't I specify a different set of request parameters for the paths? – user1871869 Sep 29 '15 at 07:32
  • No, you absolutely did not - see my answer. – Boris the Spider Sep 29 '15 at 07:33
  • 1
    You didn't specify anything different. If you want to route based on request parameters then add the `params` attribute to the `RequestMapping` annotation, currently from a mapping perspective there is nothing different. – M. Deinum Sep 29 '15 at 07:44
  • @BoristheSpider am just confused then because I thought `@RequestParam` would do this for me. I looked at http://stackoverflow.com/questions/13715811/requestparam-vs-pathvariable and that seems to say that the `@RequestParam` annotation is indeed for routing based on parameters. – user1871869 Sep 29 '15 at 16:19

1 Answers1

13

What is important to Spring to dispatch the request is the Path portion of the URL.

Both request mappings capture any value placed in the path and it is impossible to distinguish which method should be invoked. In your example code, a request to www.example.com/rest/api/datasources/foo could be handled by getLatestApiMetadata where "foo" is the datasourceName and also handled by getAllMetadata where "foo" is the apiVersion.

Tim Bender
  • 20,112
  • 2
  • 49
  • 58
  • Ah okay. but didn't I specify a different set of request parameters for each path? – user1871869 Sep 29 '15 at 07:30
  • The request parameters are all extracted from the request context with a `HandlerMethodArgumentResolver` chain after the handler method to dispatch the request to has been determined. Meaning the parameters are not useful for determining the method to invoke. – Tim Bender Sep 29 '15 at 16:15
  • Okay. that makes sense. Then how would i distinguish each by a request parameter? because I want the `getLatestMetaData` method end point to look like `/rest/api/datasources/{datasourceName}` but the `getAllMetadata` method end point to look like `/rest/api/datasources/{apiVersion}?visibility=visibility`. That is why I made `@RequestParameter` required for just the `getAllMetadata` method. – user1871869 Sep 29 '15 at 16:27
  • 1
    @user1871869 as per my (deleted) answer, **none of your request parameters are required**. – Boris the Spider Sep 29 '15 at 16:37