jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Re: StateHelper inside Repeat

From: Edward Burns <edward.burns_at_oracle.com>
Date: Wed, 25 Feb 2015 14:54:17 -0800

>>>>> On Tue, 24 Feb 2015 16:05:50 +0200, Cagatay Civici <cagatay.civici_at_gmail.com> said:

CC> When a component uses state map via stateHelper a problem occurs in
CC> case the component is inside Data iteration.

CC> For example there is a data iteration with ui:repeat from 0 to 9,
CC> comp keeps mystate in state helper in first index which is 0, for
CC> all other iterations from 1 to 9 mystate will be same.

CC> getStateHelper().put(mystate, somevalue);

CC> <ui:repeat>
CC> <my:comp />
CC> </ui:repeat>

CC> Cant the JSF runtime create a unique state map using client id of
CC> the my:comp? So that the component can have a separate state map
CC> when we try to put and get from the map.

CC> Or would you suggest setting the state value using client id like;

CC> getStateHelper().put(this.clientId + mystate, somevalue);

On Wednesday, February 25, 2015, Hanspeter <hampidu_at_gmail.com> wrote:

>>>>> On Wed, 25 Feb 2015 10:41:52 +0100, arjan tijms <arjan.tijms_at_gmail.com> said:

HP> So there might be iteraring components that do no proper children state
HP> handling per iterarion - these need to be fixed.

As Hanspeter points out, StateHolder.saveState() for an instance of a
component gets called once, even when the component is placed inside of
an iterating component. This is correct and certainly will not be
changing. I've coded up a sample app and uploaded it to
<https://java.net/projects/javaserverfaces-spec-public/downloads/download/JSF_2_3/Early%20Draft%20Review/repeatStateMap.zip>.

Here's index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:my="http://xmlns.jcp.org/jsf/component"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <head>
        <title></title>
    </head>
    <body>
        <h:form prependId="false">
            <ui:repeat value="#{userBean.fruit}" var="cur">
                <p>#{cur} <my:myInputText value="#{userBean.fruitValues[cur]}" /> </p>
            </ui:repeat>
            
            <h:commandButton value="submit" />
        </h:form>
    </body>
</html>

Here's the component

@FacesComponent(createTag = true)
public class MyInputText extends HtmlInputText {

    @Override
    public Object saveState(FacesContext context) {
        StateHelper stateHelper = this.getStateHelper(true);
        stateHelper.put("foo", "" + System.currentTimeMillis());

        Object result = super.saveState(context);
        return result;
    }

    @Override
    public void encodeAll(FacesContext context) throws IOException {
        super.encodeAll(context);
        String stateHelperValue = "" + this.getStateHelper(true).get("foo");
        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("p", this);
        writer.writeText(stateHelperValue, "stateHelperValue");
        writer.endElement("p");
    }
}

Here's the managed bean

@Named
@RequestScoped
public class UserBean implements Serializable {
    private static final long serialVersionUID = -6249152971686287687L;
    
    private List<String> fruit;
    private Map<String, String> fruitValues;

    @PostConstruct
    private void init() {
        fruit = new ArrayList<>();
        fruit.add("apple");
        fruit.add("orange");
        fruit.add("pear");
        fruit.add("banana");
        
        fruitValues = new HashMap<>();
    }
    
    public List<String> getFruit() {
        return fruit;
    }
    
    public Map<String, String> getFruitValues() {
        return fruitValues;
    }
    
}

My question: what's the problem? If you need to save state in the
component that is relative to a particular run through the items of the
enclosing collection, then it's your responsibility to make that happen
somehow within the existing design. I'm open to adding something here,
but I don't understand what. Please someone elaborate.

AT> I don't have a direct answer to Cagatay's question, but I do like to remark
AT> it would be beneficial if we'd had a proper base class for iterating
AT> components. Currently UIRepeat, UIData and what else is out there have to
AT> implement the same features and get the same fixes all the time.

I recall our old colleague Matthias Wessendorf filed
JAVASERVERFACES_SPEC_PUBLIC-935 about this. Arjan, can you please take
a look at that one and see if it fits? If so, and you care about it,
please open a new thread with Subject: [935-StampingComponent]. Please
don't discuss this further on this thread.

Thanks,

Ed

-- 
| edward.burns_at_oracle.com | office: +1 407 458 0017
|  8 days til DevNexus 2015
| 18 days til JavaLand 2015
| 28 days til CONFESS 2015