You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "Craig McClanahan (JIRA)" <ji...@apache.org> on 2006/05/26 06:24:16 UTC

[jira] Resolved: (SHALE-30) ShalePhaseListener executes ViewController.prerender twice after exception

     [ http://issues.apache.org/struts/browse/SHALE-30?page=all ]
     
Craig McClanahan resolved SHALE-30:
-----------------------------------

    Fix Version: 1.0.3
     Resolution: Fixed

Resolved in nightly build 20060526, by caching exceptions from calls to prerender() or preprocess() in a manner that will be consistent with the final solution to a "coherent exception handling" RFE (SHALE-125).


> 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
>      Fix For: 1.0.3
>  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