javaserverfaces
  1. javaserverfaces
  2. JAVASERVERFACES-2958

component with UI data can not be resolved properly by UIRepeat

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.2.1
    • Fix Version/s: 2.2.5
    • Component/s: ajax
    • Labels:
      None
    • Environment:

      glassfish 4, mojarra 2.2.1

      Description

      CODE

      package resources;
      
      import java.io.Serializable;
      import java.util.AbstractList;
      import java.util.ArrayList;
      import java.util.List;
      
      import javax.faces.view.ViewScoped;
      import javax.inject.Named;
      
      @ViewScoped
      @Named
      public class Test implements Serializable
      {
      
      	
      	/**
      	 * 
      	 */
      	private static final long serialVersionUID = 1L;
      	List<Integer> ints=new ArrayList<Integer>();
      	ValueHolderList vl=new ValueHolderList();
      	
      	public Test()
      	{
      		ints.add(1);
      		/*
      		ints.add(2);
      		ints.add(3);
      		ints.add(4);
      		ints.add(5);
      		*/
      	}
      	
      	
      	public ValueHolderList getList()
      	{
      		return vl;
      	}
      	
      	public void removeInt(int index)
      	{
      		ints.remove(index);
      	}
      	
      	public class ValueHolder
      	{
      
      		int index;
      
      		
      		public ValueHolder(int index)
      		{
      			super();
      			this.index = index;
      		}
      
      		public int getValue()
      		{
      			if (index>=ints.size())
      			{
      				return 0;
      			}
      			return ints.get(index);
      		}
      
      		public void setValue(int value)
      		{
      			ints.set(index, value);
      		}
      	}
      	public class ValueHolderList extends AbstractList<ValueHolder>
      	{
      		public ValueHolderList()
      		{
      			super();	
      		}
      
      		public ValueHolder get(int index)
      		{
      			return new ValueHolder(index);
      		}
      
      
      
      		@Override
      		public int size()
      		{
      			return ints.size();
      		}
      	}
      }
      

      Facelet

      <!DOCTYPE html>
      <html xmlns="http://www.w3.org/1999/xhtml"
      	xmlns:h="http://xmlns.jcp.org/jsf/html"
      	xmlns:f="http://xmlns.jcp.org/jsf/core"
      	xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
      <h:head>
      </h:head>
      <h:body>
      	<h:form id="f">
      		<h:panelGroup id="top">
      			<table>
      				<ui:repeat var="valueHolder" value="#{test.list}" varStatus="status" id="r">
      					<tr>
      						<td><h:inputText value="#{valueHolder.value}" id="i"></h:inputText></td>
      						<td><h:inputText value="5">
      							<f:ajax render=":f:r:0:i"></f:ajax>
      						
      						</h:inputText></td>
      						<td><h:commandButton value="remove" id="b"
      								actionListener="#{test.removeInt(status.index)}">
      								<f:ajax execute=":f:top" render=":f:top"></f:ajax>
      
      							</h:commandButton></td>
      							
      					</tr>
      				</ui:repeat>
      			</table>
      		</h:panelGroup>
      	</h:form>
      </h:body>
      </html>
      
      

      Exception

      javax.faces.FacesException: <f:ajax> contains an unknown id ':f:r:0:i' - cannot locate it in the context of the component j_idt7
      	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.getResolvedId(AjaxBehaviorRenderer.java:305)
      	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.appendIds(AjaxBehaviorRenderer.java:292)
      	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.buildAjaxCommand(AjaxBehaviorRenderer.java:225)
      	at com.sun.faces.renderkit.html_basic.AjaxBehaviorRenderer.getScript(AjaxBehaviorRenderer.java:89)
      	at javax.faces.component.behavior.ClientBehaviorBase.getScript(ClientBehaviorBase.java:103)
      	at com.sun.faces.renderkit.RenderKitUtils.getSingleBehaviorHandler(RenderKitUtils.java:1679)
      

      In this trivial example, :f:r:0:i is a perfect id for input. The issue is that when UIRepeat tries to find child components, it looks its children for a component with id 0 while 0 is the row number.

      I just use this example to reproduce the problem. In reality, I have a very complicated ID like this :ie:ConditionQuery:Conditions:r:0:QueryCondition:Operator:controls. The ID is generated from EL like this *:#

      {cc.parent.clientId}

      :controls*. As a composite component developer, I have no control whether my component is used under UIRepeat or not.

      -jason

        Activity

        Hide
        jasonzhang2002gmailcom added a comment -

        The title is not appropriate. It should be component under UIRepeat can not be resolved properly by UIRepeat. But I can not change it after I posted it.

        Show
        jasonzhang2002gmailcom added a comment - The title is not appropriate. It should be component under UIRepeat can not be resolved properly by UIRepeat . But I can not change it after I posted it.
        Hide
        jasonzhang2002gmailcom added a comment -

        If I replace ':f:r:0:i' with ':f:r:i', everything works as expected.

        Show
        jasonzhang2002gmailcom added a comment - If I replace ':f:r:0:i' with ':f:r:i', everything works as expected.
        Hide
        jasonzhang2002gmailcom added a comment -

        I read the document carefully. String in render attributes should be client ID. Given this, :f:r:i is not a valid clientID while :f:r:0:i is a valid client ID. :f:r:i works under the same table. But there is no way to support cross-row ajax interaction, or support interaction between a component out of UIRepeat and a component in a particular row in UIRepeat.

        Show
        jasonzhang2002gmailcom added a comment - I read the document carefully. String in render attributes should be client ID. Given this, :f:r:i is not a valid clientID while :f:r:0:i is a valid client ID. :f:r:i works under the same table. But there is no way to support cross-row ajax interaction, or support interaction between a component out of UIRepeat and a component in a particular row in UIRepeat.
        Hide
        Manfred Riem added a comment -

        Applied to 2.2 branch,

        svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2958, allow for f:ajax to default back to a client id, without actually resolving it."
        Sending jsf-ri/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
        Transmitting file data .
        Committed revision 12606.

        Show
        Manfred Riem added a comment - Applied to 2.2 branch, svn commit -m "Fixes https://java.net/jira/browse/JAVASERVERFACES-2958 , allow for f:ajax to default back to a client id, without actually resolving it." Sending jsf-ri/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java Transmitting file data . Committed revision 12606.
        Hide
        balusc added a comment -

        Great change. But now it never throws an exception in case of a really invalid client ID. This not anymore robust and confusing to starters. I created a new issue to improve it further: https://java.net/jira/browse/JAVASERVERFACES-3847

        Show
        balusc added a comment - Great change. But now it never throws an exception in case of a really invalid client ID. This not anymore robust and confusing to starters. I created a new issue to improve it further: https://java.net/jira/browse/JAVASERVERFACES-3847

          People

          • Assignee:
            Manfred Riem
            Reporter:
            jasonzhang2002gmailcom
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: