struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bugzi...@apache.org
Subject DO NOT REPLY [Bug 38000] New: - ShalePhaseListener executes ViewController.prerender twice after exception
Date Wed, 21 Dec 2005 23:08:38 GMT
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=38000>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=38000

           Summary: ShalePhaseListener executes ViewController.prerender
                    twice after exception
           Product: Struts
           Version: Unknown
          Platform: Other
        OS/Version: other
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Shale
        AssignedTo: dev@struts.apache.org
        ReportedBy: darren@bitcraft.ca


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().

-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org


Mime
View raw message