[ http://issues.apache.org/struts/browse/SHALE-30?page=all ]
Craig McClanahan moved STR-2703 to SHALE-30: -------------------------------------------- Project: Shale (was: Struts Action 1) Key: SHALE-30 (was: STR-2703) Component: (was: Shale) Version: (was: Unknown) Assign To: (was: Struts Developer Mailing List) > ShalePhaseListener executes ViewController.prerender twice after exception > -------------------------------------------------------------------------- > > Key: SHALE-30 > URL: http://issues.apache.org/struts/browse/SHALE-30 > Project: Shale > Type: Bug > Environment: Operating System: other > Platform: Other > Reporter: Darren Boyd > Attachments: patchfile.txt, view.patch > > In some situations when an exception is thrown from the prerender() call of a > ViewController the call will be made twice in the same request. I've come > across this when the application container is configured to forward to a JSF > page when encountering an error. > In my situation, I have configured Tomcat (in web.xml) to forward to an error > page for any '500' error. When a ViewController throws an exception from > prerender() the exception finds its way to the container which then forwards > to > the error page. Since the error page is a JSF page, the JSF lifecycle is > processed for this new 'view'. There is no ViewController mapped to the error > page. However, due to the exception previously, the > ViewController.prerender() > that was previously called gets called again. > After looking at the code I found a simple reason as to why this is happening. > The ShalePhaseListener.beforeRenderResponse(PhaseEvent) method is responsible > for calling the prerender(). This is what it looks like... > private void beforeRenderResponse(PhaseEvent event) { > Map map = > event.getFacesContext().getExternalContext().getRequestMap(); > ViewController vc = (ViewController) > map.get(ShaleConstants.VIEW_RENDERED); > if (vc == null) { > return; > } > vc.prerender(); > map.remove(ShaleConstants.VIEW_RENDERED); > } > Since the exception is being thrown from the vc.prerender() call, the > ViewController is never removed from the faces request map. Therefore, after > the forward happens and the PhaseListener gets called again, there's still a > ViewController in the request which gets called again. > I checked out the source from the repository and made a very small change to > fix > this. I basically removed the ViewController from the map before calling > prerender(). This may not be the best way to deal with this issue, but I > think > it does better represent the intention of the code (especially given the > 'contract' of ViewController). > To reproduce this, add something like the following to your web.xml file... > <error-page> > <error-code>500</error-code> > <location>/error.jsf</location> > </error-page> > Add to this whatever configuration is required to get error.jsf to work as a > JSF > page. Make sure there is no shale ViewController mapped to /error.jsf. > On a different page (make sure it is a different JSF ViewID) add a > ViewController, appropriately mapped in Shale and throw an exception from > prerender(). -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/struts/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]