Hi<br><br>It is probably that myfaces implementation of UIData do something different<br>that RI. Myfaces uses a map to hold dataModel instances to handle better<br>the use case when nested datatables occur.<br><br>The problems described on the last email are different to the one I'm trying to<br>
solve. My only intention is make note that it is possible to solve the problem<br>described on the original proposal, only do very small changes on the spec <br>(in other words the scope of the proposal is not that huge, the dataModel<br>
handling is different from the component state handling, but both problems<br>are related).<br><br>Really I would like to see a way to call markInitialState like the one described.<br>The current way to call it is a chaos. I had to put this call on different tag handlers<br>
and the order how this method is called is the inverse one than someone could<br>expect. Without this change, if someone wants to do something similar needs to<br>call clearInitialState, save and then call again to markInitialState on the code <br>
that saves the state.<br><br>The other change described, a param to indicate when the current view is using<br>partial state saving and all calls to markInitialState should occur, to diferentiate<br>between the call when the view is built and the call when a row is set is document<br>
an implementation detail that both myfaces and mojarra contains (I suppose, <br>otherwise
how ComponentHandlerDelegate implementation could know when <br>do not call this method if the current view is not using PSS ). Note the documentation<br>of ComponentHandler just says this method is called but does not says anything<br>
about the conditions, so the implementation should decide that but there is no<br>formal way to comunicate this state, but if you look closely, ComponentHandler <br>"delegate" all that steps described on the javadoc, so in reality this class does<br>
not do anything described there and that can be considered an error in the javadoc.<br>All that documentation should be on <br>TagHandlerDelegateFactory.createComponentHandlerDelegate.<br><br>regards,<br><br>Leonardo Uribe<br>
<br><div class="gmail_quote">2010/3/19 Alexander Smirnov <span dir="ltr"><<a href="mailto:asmirnov@exadel.com">asmirnov@exadel.com</a>></span><br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
The problem is far worse then you think :-( UIData itself has transient<br>
properties, the most important of them is dataModel. Standalone UIData<br>
caches model between phases, but resets it if you have enclosed<br>
iteration components that gives huge impact on performance if data model<br>
does not cache results itself. In Mojarra, UIRepeat knows about UIData<br>
but latest has no clue about repeater, so if you put data table inside<br>
the <ui:repeat> , results will be unpredictable. Is MyFaces has a better<br>
implementation ? I haven't seen deep into its UIData code for a while...<br>
Also, it is permanent pain in the complex components that require to<br>
store some information during request or work like iterator ( that are<br>
really all trees, menus, tab panels, Tomahawk columns, and more ).<br>
Numeric row ids in the data model is additional limitation for models<br>
that connected to the database in concurrent environment there<br>
additional code requires to keep references between row number and<br>
primary key; otherwise application have a chance to update/delete wrong<br>
record.<br>
For these reasons, I think that all UIRepeat/UIData should be rewritten<br>
from scratch as it already done in the Trinidad/ADF. I'll take a closer<br>
look to your patch.<br>
<div class="im"><br>
On 03/19/2010 12:07 PM, Leonardo Uribe wrote:<br>
> Hi<br>
><br>
> Yes, I know this too. In few words, all "transient" properties, that means,<br>
> all properties that are not stored in the state are not saved. There are<br>
> very<br>
> few examples. To solve this one, there are multiple alternatives. I was<br>
> thinking<br>
> on extend StateHelper interface to add some methods like<br>
> putTransientProperty and getTransientProperty. Trinidad stores all<br>
> properties<br>
> on the FacesBean object.<br>
><br>
> Anyway, I think an "mixed" solution could solve this problem: create an<br>
> interface called RowStateTransientHolder, so only the components that<br>
> implements this type of attributes could have the chance to<br>
> save and restore its state.<br>
><br>
> But note in any case, it is necessary to do something like this to solve the<br>
> use case described.<br>
><br>
> I didn't knew that localValueSet was a transient property too.<br>
><br>
> regards,<br>
><br>
> Leonardo Uribe<br>
><br>
> 2010/3/19 Alexander Smirnov <<a href="mailto:asmirnov@exadel.com">asmirnov@exadel.com</a><br>
</div>> <mailto:<a href="mailto:asmirnov@exadel.com">asmirnov@exadel.com</a>>><br>
<div><div></div><div class="h5">><br>
> I've thought about these problems for a long time too. Your proposal has<br>
> a disadvantage because per-row state is quite different from the<br>
> component state. Take a look for the UIInput implementation:<br>
> localValueSet field is never saved in the state while it should be vary<br>
> from row to row. The same thing happens to the UIForm.submitted<br>
> attribute, that has been eventually added to the UIData spec instead of<br>
> common solution, that would save/restore all local variables. My<br>
> proposal was a separate RowStateHolder interface with<br>
> save/restoreRowState methods there component developer can preserve<br>
> internal variables. In the your stenario, there should be some flag that<br>
> tells component to save all values, even these that are not supposed to<br>
> be preserved between requests.<br>
><br>
> On 03/19/2010 10:27 AM, Leonardo Uribe wrote:<br>
> > In short, this topic is an attempt to add full state to components<br>
> > inside UIData. I'll do a brief resume, so people can understand<br>
> this one<br>
> > easily.<br>
> ><br>
> > UIData uses the same component instances to render multiple rows.<br>
> > Suppose this example:<br>
> ><br>
> > <h:dataTable id="cities" var="city" value="#{country.cities}"><br>
> > <h:column><br>
> > <h:outputText value="#{city}" /><br>
> > </h:column><br>
> > </h:dataTable><br>
> ><br>
> > In the component tree it is created this hierarchy:<br>
> ><br>
> > HtmlDatatable<br>
> > UIColumn<br>
> > HtmlOutputText<br>
> ><br>
> > If we have 10 cities, the same component is used over and over to<br>
> render<br>
> > all 10 cities. The reason to do that in this way is keep state as<br>
> small<br>
> > as possible.<br>
> ><br>
> > Now let's suppose something like this:<br>
> ><br>
> > <h:dataTable id="cities" var="city" value="#{country.cities}"><br>
> > <h:column><br>
> > <h:inputText value="#{city}" /><br>
> > </h:column><br>
> > </h:dataTable><br>
> ><br>
> > It was changed the output component for an input one. If this table is<br>
> > in a form and the values are submitted, the same component is used to<br>
> > apply request values, validate and apply them to the model (update<br>
> > process). To make this possible, UIData class has some code to<br>
> preserve<br>
> > this values between phases (using EditableValueHolder interface), so<br>
> > when each phase is processed, all rows are traversed and you get the<br>
> > expected behavior.<br>
> ><br>
> > Now suppose something more complex: We have a code that use<br>
> > invokeOnComponent to change the style of my inputText. In theory, only<br>
> > one row should change. But in fact, all rows are rendered with the<br>
> same<br>
> > color. Why? because we use the same component to render all rows,<br>
> and we<br>
> > don't preserve the children component state between rows.<br>
> ><br>
> > There is a lot of issues, questions, and side effects related to this<br>
> > issue, but just to put some of them here:<br>
> ><br>
> > TOMAHAWK-1062 InputTextArea doesn't work properly inside facet<br>
> DetailStamp<br>
> > TOMAHAWK-96 Data table Scroller not working the dataTable which was<br>
> > actually contained in other DataTable<br>
> ><br>
> <a href="https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=153" target="_blank">https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=153</a><br>
> > Problems with UIData state saving<br>
> ><br>
> > Also, it is well know that one reason why people uses c:forEach in<br>
> > facelets, is because this one create "full" components per each<br>
> row. It<br>
> > is very easy to find articles on internet.<br>
> ><br>
> > Now, with jsf 2.0 we have partial state saving, so we have a chance to<br>
> > fix this one once and for all. I tried fix this one per months (maybe<br>
> > years!), but talking with Martin Marinschek on JSFDays, some ideas<br>
> came<br>
> > out and finally it was found a possibility to fix this one using the<br>
> > existing api and with little changes on the spec.<br>
> ><br>
> > The proposal is this:<br>
> ><br>
> > 1. Do not call UIComponent.markInitialState() on<br>
> > ComponentTagHandlerDelegate, as ComponentHandler javadoc says, instead<br>
> > call it after PostAddToViewEvent are published on vdl.buildView(). We<br>
> > need to call it from root to nodes, so the parent component is marked<br>
> > first. I know the place where this call comes is from trinidad tag<br>
> > handler, but this call needs to be fixed in a more predictable way.<br>
> > 2. Use an attribute on facesContext to identify when the VDL is<br>
> marking<br>
> > the initial state (in myfaces there is already an attribute called<br>
> > "org.apache.myfaces.MARK_INITIAL_STATE"). This is necessary to<br>
> indicate<br>
> > UIData instances that it is time to save the full state of all<br>
> component<br>
> > children,<br>
> > 3. Allow UIData to hold a map where the key are client ids and the<br>
> value<br>
> > are the deltas of all components per row. This map should be saved and<br>
> > restored.<br>
> > 4. Change UIData.setRowIndex() to restore and save the component<br>
> state.<br>
> ><br>
> > I'll attach a patch on myfaces issue tracker with the algorithm<br>
> proposed<br>
> > (because it is based on myfaces codebase). It was tested and it works.<br>
> > But note it is necessary to fix the javadoc for<br>
> > UIData.markInitialState(), ComponentHandler and maybe vdl.buildView(),<br>
> > so the intention is propose this change for jsf 2.0 rev A. Note this<br>
> > works only with PSS enabled because without it we don't have a<br>
> place to<br>
> > notify UIData instances that it is necessary to get the full state.<br>
> > Also, note this patch preserve backward compatibility, because the old<br>
> > way to store/save is applied after the full state is restored.<br>
> ><br>
> > Really, I have the strong temptation to apply some similar code on<br>
> > myfaces UIRepeat component (because this class is private), but I<br>
> prefer<br>
> > first ask to EG to know what you guys think about it.<br>
> ><br>
> > Suggestions are welcome,<br>
> ><br>
> > regards,<br>
> ><br>
> > Leonardo Uribe<br>
> ><br>
><br>
><br>
</div></div></blockquote></div><br>