1

In my controller I have two methods which handle requests from user.

@RequestMapping(method = RequestMethod.GET)
@PreAuthorize("hasRole('ROLE_INTERNAL_USER')")
public String homeInt() {
    return "redirect:/internal";
}

@RequestMapping(method = RequestMethod.GET)
@PreAuthorize("hasRole('ROLE_EXTERNAL_USER')")
public String homeExt() {
    return "redirect:/external";
}

Exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'loginController' bean method 
public java.lang.String de.mark.project.web.controller.LoginController.homeInt()
to {[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'loginController' bean method
public java.lang.String de.mark.project.web.controller.LoginController.homeExt() mapped.

But problem is that both methods couldn't mapped to one request method or to one URI. Is there any solution to map request in my kind of logic?

user3279337
  • 451
  • 1
  • 6
  • 14
  • The body of the method should make a decision, based on whatever information you have, and redirect to the correct url, internal or external. – Software Engineer Mar 14 '14 at 14:02
  • 1
    What do you mean by "The body of the method should make a decision"? My annotation do that job. Isn't it? – user3279337 Mar 14 '14 at 14:04
  • Presumably, you want a single URL with a single method (GET), then you'll have to use something else to decide if the correct response is internal or external. You could write a single method to respond to the request, and put an `if` statement in there at the end which results in and external or internal redirect. – Software Engineer Mar 14 '14 at 14:56
  • Really, to answer this, I need to know more about the request itself. What distinguishes an internal from an external response? How do you know if the client is internal or external? Is it just the role they have? You can't route requests by role, only by the request mapping. – Software Engineer Mar 14 '14 at 14:56

2 Answers2

1

you need to either assign different context paths to the methods:

@RequestMapping(value="/path1", method = RequestMethod.GET)
public String homeInt() {
    ...
}

@RequestMapping(value="/path2", method = RequestMethod.GET)
public String homeExt() {
   ...
}

Or assign different HTTP verbs to the two requests:

@RequestMapping(method = RequestMethod.GET)
public String homeInt() {
    ...
}

@RequestMapping(method = RequestMethod.POST)
public String homeExt() {
   ...
}

Otherwise from an HTTP perspective there is no way to know which method would be chosen, which is what the error message means: In it's current form the two method definitions are ambiguous because they have the same context path and verb.

An alternative is to write only one method, and if possible decide on the method body:

@RequestMapping(value="/path1", method = RequestMethod.GET)
public String homeIntOrExt() {
    if (... some condition ...) {
        return "redirect:/internal";
    }
    else {
        return "redirect:/external";
    }
}
Angular University
  • 42,341
  • 15
  • 74
  • 81
  • I don't really find this answer satisfactory, see here: http://stackoverflow.com/a/12574562/572954 – rwyland Apr 03 '15 at 07:51
0

Though a bit magical this is possible with Spring using RequestConditions and a custom RequestMappingHandlerMapping implementation.

For an example have a look at this.