[richfaces-issues] [JBoss JIRA] Commented: (RF-2393) Tree nested inside node of an outer tree has strange behaviour on ajax submit when there are validation errors

Mike Hanafey (JIRA) jira-events at lists.jboss.org
Thu Mar 6 10:49:57 EST 2008


    [ http://jira.jboss.com/jira/browse/RF-2393?page=comments#action_12401592 ] 
            
Mike Hanafey commented on RF-2393:
----------------------------------

This bug can be reproduced in a very simple test case, and it can be easily fixed, although it is not clear to me if this "fix" would introduce other problems.

The fix is:

class org.ajax4jsf.component.UIDataAdaptor, method public void broadcast(FacesEvent event) as the following conditional:

		if (!(rowEvent.getPhaseId() == PhaseId.RENDER_RESPONSE)) {
			this._ajaxRowKey = eventRowKey;
			// this._ajaxRowKeysMap.put(getBaseClientId(faces), eventRowKey);
		}

When the validation failure occurs in the inner tree, "this._ajaxRowKey" is never set, which means the UITree does not add the necessary client ids to the rendered areas set. If this condition on RENDER_RESPONSE phase is removed, the test case works as expected. Presumably the condition was put there for a good reason, but for the test case it does harm without doing any good that I can see.

The following diff shows the additional client ids in the "Ajax-Update-Ids" wiith the fix in place --

% diff withoutfix.txt withfix.txt
7a8,9
> Sequence:SeqTree:0:0:s
> Sequence:SeqTree:0:0:s:childs
10a13,14
> Sequence:SeqTree:input
> Sequence:SeqTree:script

Included below is a simpler view that does not use Facelet includes. In this case the inner tree does not collapse, but the bug shows up because the validation errors are not displayed:

--------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:rich="http://richfaces.org/rich"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:a4j="http://richfaces.org/a4j"
        xmlns:gx="http://genomix.es.dupont.com/faces/core"
        xmlns:trak="http://genomix.es.dupont.com/faces/trak">

<head>
    <link rel="stylesheet" type="text/css" href="../CSS/common.css"/>
</head>

<ui:composition template="/templates/main.xhtml">

<ui:define name="title">Trak:Search:LeadView</ui:define>

<ui:define name="headerSection">
    <link rel="stylesheet" type="text/css" href="../CSS/tags/leadViewHeader.css"/>
    <link rel="stylesheet" type="text/css" href="../CSS/tags/comment.css"/>
    <link rel="stylesheet" type="text/css" href="../CSS/tags/sequence.css"/>
    <script type="text/javascript">
        function GXmakeVisible(id) {
            var e = document.getElementById(id);
            if (e) {
                e.scrollIntoView();
            }
        }
    </script>
</ui:define>

<ui:define name="body">

    <h:form id="Sequence">

        <rich:tree id="CmtTree" var="citem" value="#{leadReport.lead.commentaryUiTree.rootNode}" switchType="client"
                nodeFace="#{citem.nodeFace}" adviseNodeOpened="#{leadReport.adviseNodeOpened}" toggleOnClick="false" rendered="false">
            <!-- at elvariable id="citem" type="genomix.tractor.CommentUiTree.CommentUi"-->
            <rich:treeNode id="top" type="top" nodeClass="C-wrappingTreeNode">
                <a4j:commandButton id="addTopComm" immediate="true" image="/images/element_add-24x24.png" alt="ADD"
                        actionListener="#{leadReport.lead.commentaryUiTree.actionListenerAddTopComment}" reRender="CmtTree"
                        title="Add a new TOP LEVEL comment." style="vertical-align: middle;"
                        oncomplete="GXmakeVisible('Commentary:CmtTree:0:#{citem.addTopCommentNodeId}:ec')"/>
                <a4j:commandButton id="topSaveButton" immediate="true" value="Ajax Save" reRender="CmtTree" title="#{msg['act.save']}"/>
                <h:outputText value="#{citem.rootData}"/>
                <trak:message for="addTopComm"/>
            </rich:treeNode>
            <rich:treeNode id="c" type="c" nodeClass="C-wrappingTreeNode">
                <trak:comment id="cmtNode" lead="#{leadReport.lead}" cmt="#{citem}" reRender="CmtTree"/>
            </rich:treeNode>
            <rich:treeNode id="ec" type="ec" nodeClass="C-wrappingTreeNode">
                <table class="C-vmargin COMMENT">
                    <tr class="COMMENT-title">
                        <td colspan="3">
                            <h:inputText id="title" value="#{citem.appData.title}" required="true" validator="#{citem.validateTitle}"
                                    styleClass="COMMENT-input">
                                <gx:trimString/>
                            </h:inputText>
                            <rich:message for="title"/>
                        </td>
                    </tr>
                    <tr class="COMMENT-body">
                        <td colspan="3">
                            <h:inputTextarea id="body" value="#{citem.appData.body}" required="true" validator="#{citem.validateTitle}"
                                    rows="4"
                                    styleClass="COMMENT-input">
                                <gx:trimString/>
                            </h:inputTextarea>
                            <rich:message for="body"/>
                        </td>
                    </tr>
                    <tr class="COMMENT-footer">
                        <td>
                            <a4j:commandButton id="saveButton" value="Ajax Save" actionListener="#{citem.actionListenerSaveComment}"
                                    reRender="CmtTree"
                                    title="#{msg['act.save']}"/>
                            <h:commandButton id="saveButtonNA" value="Plain Save" actionListener="#{citem.actionListenerSaveComment}"
                                    title="#{msg['act.save']}"/>
                            <a4j:commandButton id="nothingButton" value="Ajax Immediate" immediate="true"
                                    actionListener="#{citem.actionListenerNothing}" reRender="CmtTree"
                                    title="#{msg['act.save']}"/>
                            <a4j:commandButton id="quitButton" value="Ajax Quit" actionListener="#{citem.actionListenerQuitComment}"
                                    immediate="true"
                                    reRender="CmtTree" title="#{msg['act.quit']}" style="margin-left:8px"/>
                            <rich:message for="saveButton"/>
                            <rich:message for="saveButtonNA"/>
                            <rich:message for="quitButton"/>
                        </td>
                        <td/>
                        <td class="COMMENT-whoWhen">By: #{citem.appData.whoWhen.namesAndDates}</td>
                    </tr>
                </table>
            </rich:treeNode>
        </rich:tree>

        <rich:tree id="SeqTree" var="sitem" value="#{leadReport.lead.sequenceUiTree.rootNode}" switchType="client"
                nodeFace="#{sitem.nodeFace}" adviseNodeOpened="#{leadReport.adviseNodeOpened}" toggleOnClick="false" rendered="true">
            <!-- at elvariable id="sitem" type="genomix.tractor.SequenceUiTree.SequenceUi"-->
            <rich:treeNode id="top" type="top" nodeClass="C-wrappingTreeNode">
                <h:outputText value="#{sitem.rootData}"/>
            </rich:treeNode>
            <rich:treeNode id="s" type="s" nodeClass="C-wrappingTreeNode">
                <rich:tree id="CmtTree" var="citem" value="#{leadReport.lead.commentaryUiTree.rootNode}" switchType="client"
                        nodeFace="#{citem.nodeFace}" adviseNodeOpened="#{leadReport.adviseNodeOpened}" toggleOnClick="false">
                    <!-- at elvariable id="citem" type="genomix.tractor.CommentUiTree.CommentUi"-->
                    <rich:treeNode id="top" type="top" nodeClass="C-wrappingTreeNode">
                        <a4j:commandButton id="addTopComm" immediate="true" image="/images/element_add-24x24.png" alt="ADD"
                                actionListener="#{leadReport.lead.commentaryUiTree.actionListenerAddTopComment}" reRender="CmtTree"
                                title="Add a new TOP LEVEL comment." style="vertical-align: middle;"
                                oncomplete="GXmakeVisible('Commentary:CmtTree:0:#{citem.addTopCommentNodeId}:ec')"/>
                        <a4j:commandButton id="topSaveButton" immediate="true" value="Ajax Save" reRender="CmtTree" title="#{msg['act.save']}"/>
                        <h:outputText value="#{citem.rootData}"/>
                        <trak:message for="addTopComm"/>
                    </rich:treeNode>
                    <rich:treeNode id="c" type="c" nodeClass="C-wrappingTreeNode">
                        <trak:comment id="cmtNode" lead="#{leadReport.lead}" cmt="#{citem}" reRender="CmtTree"/>
                    </rich:treeNode>
                    <rich:treeNode id="ec" type="ec" nodeClass="C-wrappingTreeNode">
                        <table class="C-vmargin COMMENT">
                            <tr class="COMMENT-title">
                                <td colspan="3">
                                    <h:inputText id="title" value="#{citem.appData.title}" required="true" validator="#{citem.validateTitle}"
                                            styleClass="COMMENT-input">
                                        <gx:trimString/>
                                    </h:inputText>
                                    <rich:message for="title"/>
                                </td>
                            </tr>
                            <tr class="COMMENT-body">
                                <td colspan="3">
                                    <h:inputTextarea id="body" value="#{citem.appData.body}" required="true" validator="#{citem.validateTitle}"
                                            rows="4"
                                            styleClass="COMMENT-input">
                                        <gx:trimString/>
                                    </h:inputTextarea>
                                    <rich:message for="body"/>
                                </td>
                            </tr>
                            <tr class="COMMENT-footer">
                                <td>
                                    <a4j:commandButton id="saveButton" value="Ajax Save" actionListener="#{citem.actionListenerSaveComment}"
                                            reRender="CmtTree"
                                            title="#{msg['act.save']}"/>
                                    <h:commandButton id="saveButtonNA" value="Plain Save" actionListener="#{citem.actionListenerSaveComment}"
                                            title="#{msg['act.save']}"/>
                                    <a4j:commandButton id="nothingButton" value="Ajax Immediate" immediate="true"
                                            actionListener="#{citem.actionListenerNothing}" reRender="CmtTree"
                                            title="#{msg['act.save']}"/>
                                    <a4j:commandButton id="quitButton" value="Ajax Quit" actionListener="#{citem.actionListenerQuitComment}"
                                            immediate="true"
                                            reRender="CmtTree" title="#{msg['act.quit']}" style="margin-left:8px"/>
                                    <rich:message for="saveButton"/>
                                    <rich:message for="saveButtonNA"/>
                                    <rich:message for="quitButton"/>
                                </td>
                                <td/>
                                <td class="COMMENT-whoWhen">By: #{citem.appData.whoWhen.namesAndDates}</td>
                            </tr>
                        </table>
                    </rich:treeNode>
                </rich:tree>

            </rich:treeNode>
        </rich:tree>
    </h:form>

    <h:form id="clear">
        <h:commandButton id="clearSession" value="Invalidate Session" actionListener="#{leadReport.actionListenerInvalidateSession}"/>
        <h:commandButton id="submit" value="Submit" actionListener="#{leadReport.actionListenerSubmit}"/>
    </h:form>
</ui:define>
</ui:composition>
</html>
-------------------------------------------------------------------------------------------------------------------

> Tree nested inside node of an outer tree has strange behaviour on ajax submit when there are validation errors
> --------------------------------------------------------------------------------------------------------------
>
>                 Key: RF-2393
>                 URL: http://jira.jboss.com/jira/browse/RF-2393
>             Project: RichFaces
>          Issue Type: Bug
>    Affects Versions: 3.1.4
>         Environment: Glassfish v2, JSF RI 1.2
>            Reporter: Mike Hanafey
>         Assigned To: Nick Belaevski
>             Fix For: 3.2.0
>
>         Attachments: NestedTree.tar.gz, NestedTree.war
>
>
> I have situation where there is an outer tree whose nodes have an inner tree. Specifically, the outer tree is over DNA sequences, and each DNA sequence may have a tree of comments attached to it.
> Both the inner and outer trees have a couple of faces, one is used when a node is in display mode, and the other when it is in edit mode.
> If the inner tree is put into edit mode at a node (via an ajax request) and a validation error occurs on a second ajax request to submit the edits, the whole inner tree for that node disappears. It can be recovered by doing a browser redisplay. If there is no validation error, the edit works as expected
> Looking at the XmlHttpRequest response when there is a validation error shows that the response does not contain the expected tree nodes.
> When this same comment tree code (both the backing beans and the facelets views) is applied on an unnested tree this problem does not occur. 
> A test war is attached (the war is big only because it includes the library dependencies -- the test code itself is small).
> To demonstrate, deploy the war and look at the top page.
> Click on the + next to "Comments" (this is the un-nested tree). Click "Ajax Save". Observe the "Value is required" messages.
> Enter something into the first textfield, and do the "Ajax Save". Now a custom validation message appears.
> Now for the first strangeness. Enter something in both the textfield and the textarea. The custom validation message appears on both inputs, but now the inputs just made are erased. When only one of these fields have data, the data entered in the other field is preserved, and I believe the clearing of input data is another error, but not the one in the title of this this issue.
> To see the main issue, open the tree labeled "Sequences". This has a comments tree just like the one above nested inside the sequence node.
> Click on the + next the "Comments" under "Sequences".
> Click on "Ajax Save". Now instead of seeing the "Value is required" error, the inner tree node collapses. Click on the "Submit" button, an reopen the "Sequences" tree to see that the inner tree is in fact still intact.
> Click on "Ajax Immediate". Now the tree does not collapse. The only difference is this button is immediate, so the validation steps are not done.
> Finally, clicking on "Plain Save" shows the expected validation errors (now the Sequence tree collapses after the submit so it must be manually opened, but I guess this is expected behavior because the open / close state is not maintained across the request). The problem where the inputs that fail validation are erased remains even with this non-ajax update mode).

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the richfaces-issues mailing list