View Full Version : Invoke another Controller without using Response.sendRedirec
theMesser
Oct 2nd, 2004, 03:59 PM
Currently, in my Controller, I'll perform some type of logic and then wish to view another page so I do a response.sendRedirect("/some/URL") and hardcore the name of the URL so that the correct Controller associated with that URL is invoked. Is there a better way to do this? This way is crappy because I'm hardcoding the URL.
When I look at the examples like JPetstore, all of the controllers just return a ModelAndView. None of them seem to suffer this problem. Am I thinking about this all wrong? Don't get me wrong, almost all of my Controllers return ModelAndViews but sometimes I need to invoke another Controller to render the proper view instead of duplicating the logic in the same Controller.
I would love to hear what the experienced developers have to say about this.
--JS
rharing
Oct 2nd, 2004, 05:20 PM
That problem was one of the reasons I started my own sourceforge spring project. It is available at www.competities.com/springworkflow and developed to solve this very annoying problem. All the controllers and corresponding actions are described in an xml file. When a controller should invoke another controller, that controller throws a WorkflowRedirectException with a key that correspondents to another action and the workflow system will then invoke the referred controller. As a side benefit you dont have to code your own navigation javascripts or hrefs anymore if you have different options on a page resulting in different submit requests and because all the actions are centralized in a xml, its easy to turn on and off specific actions for specific pages.
HTH
theMesser
Oct 2nd, 2004, 06:14 PM
Hmmmm. This problem merits a branch? I didn't realize it was that serious. :-) But c'mon, there must be another way. What do the Spring guys think of this? Thanks for the reply, by the way.
--JS
rharing
Oct 3rd, 2004, 03:32 AM
Yeah pathetic isnt it. Well everyone wants to have their 15 minutes of fame and since I dont fancy going on the tv telling about how I have the biggest collection of used toiletpaper in the world, I created a sourceforge project :)
But no, that wasnt the only reason I started that subproject. The main reason was the abillity to have all your actions centralized in a big xml file so that you can turn actions on and off on specific pages without having to change the jsp's. And as a side effect, the stacking of controllers emerged from that.
Your problem could also be solved by a returning a RedirectView("/some/place") I think, but that would still leave you with the hardcoded url. But that isnt so weird, since the orignal requests all come with hardcoded urls.
Another way could be to get your controller from the applicationContext and invoke the correct methods. This, of course, is more likely to work when your next controller is a multiactioncontroller, since that doesnt have binder and validate methods associated with it that will be performed without you knowing it.
Hope that helps more
ojolly
Oct 3rd, 2004, 07:17 AM
I don't think you need that many sophistication.
If you want to forward the job of a controller to another, you can make a
return otherController.handleRequestInternal(request,resp onse);
which will return the ModelAndView of another controller which will have made its submiting action.
If you only want to have for view an external url, you can return a MovelAndView by an instance of RedirectView as view instead of just a name (even if generally, for internal ressource, using a name and a ViewResolver is a better approach) like this
return new ModelAndView(new RedirectView("/html/success.html", false), model);
the boolean indicates whether the url is relative to the ServletContext (useful for being independant of the web application context) or not.
Does it solve your problem ?
Olivier
Colin Sampaleanu
Oct 3rd, 2004, 09:47 AM
I don't think you need that many sophistication.
If you want to forward the job of a controller to another, you can make a
return otherController.handleRequestInternal(request,resp onse);
which will return the ModelAndView of another controller which will have made its submiting action.
If you only want to have for view an external url, you can return a MovelAndView by an instance of RedirectView as view instead of just a name (even if generally, for internal ressource, using a name and a ViewResolver is a better approach) like this
return new ModelAndView(new RedirectView("/html/success.html", false), model);
the boolean indicates whether the url is relative to the ServletContext (useful for being independant of the web application context) or not.
I wouldn't call handleRequestInternal on another controller. That's subverting the normal get or post process that should be hitting that controller. You'll be using the existing request object for example, with all the params that were passed into the current controller.
But using a new RediirectView is ok as long as you just externalize the URL so the first controller doesn't have it hard-coded inside. Then it can be set in the appcontext along with view names and handler mappings, etc.
return new ModelAndView(new RedirectView(getMyOtherControllerUrl(), true), model);
In this case the RedirectView is marked as true for the context relative flag, which is preferred so the path can be relative to the context (should still start with a '/').
I have been playing around with the idea of creating a special view resolver which would detect view names of the type
redirect:xxxxxx
and would be placed at the beginning of the view resolver chain, and would automatically use a redirect view. This would arguably be a bit cleaner even, as the first controller wouldn't even know that a redirect is involved.
theMesser
Oct 3rd, 2004, 12:52 PM
Ok, I got it. RedirectView was the solution I was looking for. Thanks guys!
--JS
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.