[richfaces-issues] [JBoss JIRA] (RF-12281) rich:tree is iterated multiple times when item is selected

Lukáš Fryč (JIRA) jira-events at lists.jboss.org
Fri Nov 30 09:41:21 EST 2012


    [ https://issues.jboss.org/browse/RF-12281?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12738500#comment-12738500 ] 

Lukáš Fryč commented on RF-12281:
---------------------------------

Hey Alex,

I have created sample with 2-level deep tree, once I select a root node - level 0 using zero-based counting, then I get:

{code}
15:32:40,181 INFO  [stdout] (http--0.0.0.0-8080-4) Before RESTORE_VIEW 1
15:32:40,185 INFO  [stdout] (http--0.0.0.0-8080-4) After RESTORE_VIEW 1
15:32:40,186 INFO  [stdout] (http--0.0.0.0-8080-4) Before APPLY_REQUEST_VALUES 2
15:32:40,197 INFO  [stdout] (http--0.0.0.0-8080-4) Inside Selection Change Action
15:32:40,198 INFO  [stdout] (http--0.0.0.0-8080-4) After APPLY_REQUEST_VALUES 2
15:32:40,198 INFO  [stdout] (http--0.0.0.0-8080-4) Before PROCESS_VALIDATIONS 3
15:32:40,206 INFO  [stdout] (http--0.0.0.0-8080-4) After PROCESS_VALIDATIONS 3
15:32:40,206 INFO  [stdout] (http--0.0.0.0-8080-4) Before UPDATE_MODEL_VALUES 4
15:32:40,215 INFO  [stdout] (http--0.0.0.0-8080-4) After UPDATE_MODEL_VALUES 4
15:32:40,215 INFO  [stdout] (http--0.0.0.0-8080-4) Before INVOKE_APPLICATION 5
15:32:40,215 INFO  [stdout] (http--0.0.0.0-8080-4) After INVOKE_APPLICATION 5
15:32:40,215 INFO  [stdout] (http--0.0.0.0-8080-4) Before RENDER_RESPONSE 6
15:32:40,226 INFO  [stdout] (http--0.0.0.0-8080-4) After RENDER_RESPONSE 6
{code}

When I select an inner node on level 1:

{code}
15:35:13,702 INFO  [stdout] (http--0.0.0.0-8080-4) Before RESTORE_VIEW 1
15:35:13,707 INFO  [stdout] (http--0.0.0.0-8080-4) After RESTORE_VIEW 1
15:35:13,708 INFO  [stdout] (http--0.0.0.0-8080-4) Before APPLY_REQUEST_VALUES 2
15:35:13,725 INFO  [stdout] (http--0.0.0.0-8080-4) getChildAt(0)
15:35:13,725 INFO  [stdout] (http--0.0.0.0-8080-4) Inside Selection Change Action
15:35:13,726 INFO  [stdout] (http--0.0.0.0-8080-4) After APPLY_REQUEST_VALUES 2
15:35:13,726 INFO  [stdout] (http--0.0.0.0-8080-4) Before PROCESS_VALIDATIONS 3
15:35:13,734 INFO  [stdout] (http--0.0.0.0-8080-4) After PROCESS_VALIDATIONS 3
15:35:13,735 INFO  [stdout] (http--0.0.0.0-8080-4) Before UPDATE_MODEL_VALUES 4
15:35:13,743 INFO  [stdout] (http--0.0.0.0-8080-4) After UPDATE_MODEL_VALUES 4
15:35:13,744 INFO  [stdout] (http--0.0.0.0-8080-4) Before INVOKE_APPLICATION 5
15:35:13,744 INFO  [stdout] (http--0.0.0.0-8080-4) After INVOKE_APPLICATION 5
15:35:13,744 INFO  [stdout] (http--0.0.0.0-8080-4) Before RENDER_RESPONSE 6
15:35:13,746 INFO  [stdout] (http--0.0.0.0-8080-4) getChildAt(0)
15:35:13,754 INFO  [stdout] (http--0.0.0.0-8080-4) After RENDER_RESPONSE 6
{code}

When I select leaf on level 2:

{code}
15:35:49,321 INFO  [stdout] (http--0.0.0.0-8080-4) Before RESTORE_VIEW 1
15:35:49,327 INFO  [stdout] (http--0.0.0.0-8080-4) After RESTORE_VIEW 1
15:35:49,328 INFO  [stdout] (http--0.0.0.0-8080-4) Before APPLY_REQUEST_VALUES 2
15:35:49,341 INFO  [stdout] (http--0.0.0.0-8080-4) getChildAt(0)
15:35:49,341 INFO  [stdout] (http--0.0.0.0-8080-4) getChildAt(0)
15:35:49,341 INFO  [stdout] (http--0.0.0.0-8080-4) Inside Selection Change Action
15:35:49,342 INFO  [stdout] (http--0.0.0.0-8080-4) After APPLY_REQUEST_VALUES 2
15:35:49,342 INFO  [stdout] (http--0.0.0.0-8080-4) Before PROCESS_VALIDATIONS 3
15:35:49,350 INFO  [stdout] (http--0.0.0.0-8080-4) After PROCESS_VALIDATIONS 3
15:35:49,350 INFO  [stdout] (http--0.0.0.0-8080-4) Before UPDATE_MODEL_VALUES 4
15:35:49,357 INFO  [stdout] (http--0.0.0.0-8080-4) After UPDATE_MODEL_VALUES 4
15:35:49,357 INFO  [stdout] (http--0.0.0.0-8080-4) Before INVOKE_APPLICATION 5
15:35:49,357 INFO  [stdout] (http--0.0.0.0-8080-4) After INVOKE_APPLICATION 5
15:35:49,357 INFO  [stdout] (http--0.0.0.0-8080-4) Before RENDER_RESPONSE 6
15:35:49,359 INFO  [stdout] (http--0.0.0.0-8080-4) getChildAt(0)
15:35:49,360 INFO  [stdout] (http--0.0.0.0-8080-4) getChildAt(0)
15:35:49,368 INFO  [stdout] (http--0.0.0.0-8080-4) After RENDER_RESPONSE 6
{code}

There is really nothing avoidable in calling {{getChildAt}}.
For each level excluding root the {{getChildAt}} method is called at most once per phase.

The general recommendation is making {{getChildAt}} cached during whole request (e.g. using request scoped bean state). Then, first phase will may be more demanding, but other phases will be fast.
                
> rich:tree is iterated multiple times when item is selected
> ----------------------------------------------------------
>
>                 Key: RF-12281
>                 URL: https://issues.jboss.org/browse/RF-12281
>             Project: RichFaces
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>          Components: component-tree
>    Affects Versions: 4.2.2.Final
>            Reporter: Alex Vb
>            Assignee: Lukáš Fryč
>             Fix For: 4.3.0.M3
>
>
> I have a decently sized tree and I'm using the selectionChangeListener in combination with toggleType="client" selectionType="ajax" render="node" to trigger a selection event on the server. The panelGroup "node" is re-rendered afterwards but it takes 1-2 seconds for each request. After enabling some debug logging I noticed that the entire tree is iterated 4 times for each request. Note a small test-tree exhibiting the same behavior:
> {code}
> 2012-05-22 08:39:29.287 DEBUG CustomPhaseListener - Before phase: APPLY_REQUEST_VALUES 2
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChildrenKeysIterator(0)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChild(1)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChildrenKeysIterator(1)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.287 DEBUG Bean - selectionChanged()
> 2012-05-22 08:39:29.287 DEBUG CustomPhaseListener - After phase: APPLY_REQUEST_VALUES 2
> 2012-05-22 08:39:29.287 DEBUG CustomPhaseListener - Before phase: PROCESS_VALIDATIONS 3
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChildrenKeysIterator(0)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChild(1)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChildrenKeysIterator(1)
> 2012-05-22 08:39:29.287 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.302 DEBUG CustomPhaseListener - After phase: PROCESS_VALIDATIONS 3
> 2012-05-22 08:39:29.302 DEBUG CustomPhaseListener - Before phase: UPDATE_MODEL_VALUES 4
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChildrenKeysIterator(0)
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChild(1)
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChildrenKeysIterator(1)
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.302 DEBUG CustomPhaseListener - After phase: UPDATE_MODEL_VALUES 4
> 2012-05-22 08:39:29.302 DEBUG CustomPhaseListener - Before phase: INVOKE_APPLICATION 5
> 2012-05-22 08:39:29.302 DEBUG CustomPhaseListener - After phase: INVOKE_APPLICATION 5
> 2012-05-22 08:39:29.302 DEBUG CustomPhaseListener - Before phase: RENDER_RESPONSE 6
> 2012-05-22 08:39:29.302 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.318 DEBUG TreeNodeBase - getChildrenKeysIterator(0)
> 2012-05-22 08:39:29.318 DEBUG TreeNodeBase - getChild(1)
> 2012-05-22 08:39:29.318 DEBUG TreeNodeBase - getChildrenKeysIterator(1)
> 2012-05-22 08:39:29.318 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.318 DEBUG TreeNodeBase - getChild(2)
> 2012-05-22 08:39:29.318 DEBUG CustomPhaseListener - After phase: RENDER_RESPONSE 6
> {code}
> On the rather large tree each iteration takes 300-500 ms which explains the slow behavior. I have played around with every setting I could find, if selectionType is set to "client" the tree is iterated only once (during the render response phase) but the selection event does not seem to be triggered. If toggleType is set to ajax, only the "expanded" parts of the tree are iterated.
> I have no idea why the iteration is necessary for all these phases but I "fixed" it in my implementation by recompiling the org.richfaces.component.TreeRange class with an updated method:
> {code:java}
>     public boolean shouldIterateChildren() {
>     	if (tree.isLeaf())
>     		return false;
>     	else {
> 	    	char separatorChar = UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());
> 	    	String clientId = tree.getClientId();
> 	    	boolean render = false;
> 	    	for (String idToRender : FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds()) {
> 	    		// render the tree if you explicitly mention either the client id (e.g. "menuForm:tree") or the parent component client id (e.g. "menuForm")
> 	    		// note that when clicking on an object in the tree, the following render target is requested: menuForm:tree at selection
> 	    		if (clientId.equals(idToRender) || clientId.matches(idToRender + separatorChar + ".*")) {
> 	    			render = true;
> 	    			break;
> 	    		}
> 	    	}
> 	    	// always render if it's not a postback
>     		return render || !FacesContext.getCurrentInstance().isPostback();
> 	    }
>     }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira



More information about the richfaces-issues mailing list