4

In Spring 3 MVC, I have a controller that I call SettingsController, and it has methods such as displayUsers() for displaying a list of users, saveUser(), and deleteUser(). SettingsContoller also controls roles and other things.

I'd love to be able to use URL routing such that /settings/users would call displayUsers(), /settings/users/save would call saveUser(), and /settings/users/delete would call deleteUser().

My code is below, and I'm getting the error message that follows the code. What am I doing wrong? Thanks!

@Controller
@RequestMapping("/settings")
public class SettingsController {

    @Transactional
    @RequestMapping(value = {"/users/save"}, method = {RequestMethod.POST})
    public ModelAndView saveUser(details removed){
        //details removed
    }

    @RequestMapping(value = {"/users/delete"}, method = {RequestMethod.POST})
    public ModelAndView deleteUser(details removed){
       //details removed
    }

    @RequestMapping(value = {"/users"}, method = RequestMethod.GET)
    public ModelAndView settingsUsers(details removed){
      //details removed
    }

}

Error:

HTTP ERROR: 500

Could not resolve view with name 'settings/users/delete' in servlet with name 'spring'
RequestURI=/das-portal/srv/settings/users/delete

Caused by:

javax.servlet.ServletException: Could not resolve view with name 'settings/users/delete' in servlet with name 'spring'
    at        org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1029)
...
Ryan
  • 22,332
  • 31
  • 176
  • 357

2 Answers2

2

It looks to me like you've set up your controller correctly. As you pointed out, the problem might be in how Spring parses annotations upon start up.

How did you configure Sprint to parse annotations such as @Controller? Do you explicitly set up any sort of HandlerMapping? If you use <context:component-scan>, then it registers a DefaultAnnotationHandlerMapping for you.

The good news is that you can chain multiple handler mapping classes together. The DispatcherServlet will check each one in the order that you specify via the order property of the handler mapping beans (in other words, use the order property to indicate the precedence of your handlers).

So, throw <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> into your configuration and set its order property as appropriate.

jtoberon
  • 8,706
  • 1
  • 35
  • 48
  • I'm just returning a redirect to a different view. It all works fine if I have less than 3 segments deep (e.g. if I had settings/userDelete instead of settings/users/delete). I just found this ( http://stackoverflow.com/questions/4196577/spring-mvc-how-to-map-uri-templates-in-the-form-of-a-b-c ) which looks to me like it might be related, but I can't figure out a solution. – Ryan Jun 28 '11 at 22:10
  • Yes, I'm using ControllerClassNameHandlerMapping (need to). ` ` – Ryan Jun 29 '11 at 16:46
  • When I comment out the 2nd of these 3 beans, this works: ` ` but I need that 2nd bean to work too, as the 2nd priority, but it has no Order prop. Thanks. – Ryan Jun 30 '11 at 16:22
  • I think I got this to work! ` ` – Ryan Jun 30 '11 at 16:56
1

What about using just one method checking mode?

@RequestMapping(value = "/users/{action}", method = RequestMethod.POST)
public String userAction(@PathVariable String action, ...) {
  if (mode.equals("save")) {
      //your save code here
  }
}
StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • I've thought about this, but the {action} would need to accept 2 words split by a / , which is doubtful. Plus, it just doesn't seem "right". I feel like what I'm trying to do is simple and I'm just not aware of the approach. – Ryan Jun 29 '11 at 16:49