dev@jsftemplating.java.net

Re: JSFTemplating: help with navigate() or redirect()

From: Ken Paulsen <Ken.Paulsen_at_Sun.COM>
Date: Tue, 05 Sep 2006 19:01:00 -0700

Hi Anissa,

As I mentioned to you on the phone, the redirect handler is getting
called multiple times which is invalid and causes the exception.
Finding out why took me a lot longer than I expected, though!

It looked like the handler was getting registered 2x, suggesting a bug
in how the actionListener or handlers were registered / dispatched.
Well, I'm happy to say that after looking closely at that code and
debugging it fairly well (for this code path at least), I didn't find
any problems at all. It finally occurred to me that perhaps the tree.js
was broken (it wasn't), but that led me to the Hyperlink JavaScript,
which causes a side-effect on the <form>.

The Hyperlink adds <hidden> fields through JavaScript to the <form>. It
does this to add necessary information to the request to properly decode
the Hyperlink. However, it doesn't clean up after itself. So when you
click multiple Hyperlinks, it starts processing every Hyperlink that
you've previously clicked as well. This isn't as noticeable when you're
not doing a redirect because the server does throw an exception to catch
this. And of course you don't notice it if you're not using frames
because the page (and the modified <form> element) is replaced with your
new page.

If you want a test case, drop the 2 attached .jsf files into a directory
and visit "index.jsf". Clicking on the links on the left will show the
results on the right. Notice that once you've selected a link, the
value on the right remains. If you select a value on the right, only
the link you clicked is shown as "clicked". If you then click a link on
the left, it will again show you all values you've clicked in the past.
This is all b/c the frame on the left doesn't get reloaded and therefor
queues up all the hidden fields added by the Hyperlinks that you
clicked... tricking JSF into thinking you clicked multiple hyperlinks.

I sent an email to the Hyperlink component developers asking them what's
up... we'll see what they say.

Ken

Anissa Lam wrote:
>
> I need some help with doing navigate() or redirect()
>
> <dynamicTreeNode
> ...
> ... >
> <!childCommand
> setAttribute(key="click" value="$this{component}");
>
> *redirect(page="resources/jdbcResourceEdit.jsf?name=#{click.text}" );*
> />
> </dynamicTreeNode>
>
>
> When the dynamic Tree Node is pressed, i need to display another page
> with request parameter specified. If i use navigate() the request
> parameter is not available at the resulting page.
> If i use redirect(), it works fine but will only work *once.* If
> i press other dynamic tree node, i will get a 500 Error in the
> browser. If i reload the tree, the redirect() will work for one
> time again.
> Here is the stack trace :
> [#|2006-09-04T14:32:11.362-0700|SEVERE|sun-appserver-ee9.1|javax.enterprise.system.container.web|_ThreadID=16;_ThreadName=httpWorkerThread-8080-1;_RequestID=41a7d89c-1b97-444b-9745-ddf2c658a581;|StandardWrapperValve[FacesServlet]:
> PWC1406: Servlet.service() for servlet FacesServlet threw exception
> java.lang.IllegalStateException
> at
> org.apache.coyote.tomcat5.CoyoteResponseFacade.sendRedirect(CoyoteResponseFacade.java:433)
> at
> com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:424)
> at
> com.sun.jsftemplating.handlers.NavigationHandlers.redirect(NavigationHandlers.java:150)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:585)
> at
> com.sun.jsftemplating.layout.descriptors.handler.Handler.invoke(Handler.java:335)
> at
> com.sun.jsftemplating.layout.descriptors.LayoutElementBase.dispatchHandlers(LayoutElementBase.java:332)
> at
> com.sun.jsftemplating.layout.descriptors.LayoutElementBase.dispatchHandlers(LayoutElementBase.java:312)
> at
> com.sun.jsftemplating.layout.event.CommandActionListener.invokeCommandHandlers(CommandActionListener.java:132)
> at
> com.sun.jsftemplating.layout.event.CommandActionListener.processAction(CommandActionListener.java:80)
> at javax.faces.event.ActionEvent.processListener(ActionEvent.java:77)
>
> Any suggestion on what i maybe missing in using redirect () ?
>
> thanks
> Anissa



<sun:page>
    <sun:html>
        <sun:head id="head" title="test" />

        <sun:frameSet cols="25%, *">
            <sun:frame name="index" title="nav" url="test.jsf" />
            <sun:frame name="main" title="content" />
        </sun:frameSet>

    </sun:html>
</sun:page>


<sun:page>
    <sun:html>
        <sun:head id="head" />
        <sun:body>
            <sun:form id="form">
                <staticText value="Link1 = #{link1}<br\>" />
                <staticText value="Link2 = #{link2}<br\>" />
                <staticText value="Link3 = #{link3}<br\>" />
                <sun:hyperlink target="main" text="Link1">
                    <!command
                        setAttribute(key="link1", value="Clicked!");
                    />
                </sun:hyperlink>
                "<br />
                <sun:hyperlink target="main" text="Link2">
                    <!command
                        setAttribute(key="link2", value="Clicked!");
                    />
                </sun:hyperlink>
                "<br />
                <sun:hyperlink target="main" text="Link3">
                    <!command
                        setAttribute(key="link3", value="Clicked!");
                    />
                </sun:hyperlink>
                "<br />
            </sun:form>
         </sun:body>
     </sun:html>
 </sun:page>