There is a subtle but important bug when f:metadata sections are processed. Between the view metadata is created and the whole view is built, facelets algorithm discard and recreate all components. In typical situations this effect is not visible, because there is a description spec code that hide this effect. See UIViewParameter.setSubmittedValue() javadoc:
"... PENDING (docs) Interesting that submitted value isn't saved by the parent ..."
The discussion comes from issue:
MYFACES-2645 The view state is saved before encodeAll() is called on every UIViewParameter in an AJAX request
In that time, I commented the following:
LU>> The javadocs of UIViewParameter.encodeAll says this:
LU>> ".......Called specially by UIViewRoot.encodeEnd(javax.faces.context.FacesContext), this method simply sets the submitted value to be the return from
LU>> My question is why? isn't that bad?
In that time, the discussion was related to how to preserve the view params in ajax request. The argument was submittedValue is set to null on process validations, and it is necessary a way to preserve that value into the state.
The solution in that issue is valid, but what happen when validation fails? submittedValue should not change, so why its value is lost before encodeAll() is processed?.
By performance reasons, two different facelets are used for a view: one for create metadata that just process stuff inside <f:metadata> and the other for build the whole view (including metadata too). Since there are two different facelets, generated in different way, the associated tagId is different and then the generated ComponentSupport.MARK_CREATED identifier is different too. Then, when the whole view is processed, facelets cannot identify the component as the same, so it is removed and created again, and in the process submittedValue and localValue are discarded, looking as if they are set to null.
The solution is ensure facelets generate the same unique ids in ComponentSupport.MARK_CREATED when f:metadata is processed, no matter if the metadata facelet or the normal facelet process the view. CompilationManager.nextTagId() uses the alias and a counter to derive an unique tag id, so it will obviously generate different tags, so the idea is ignore that part of the unique id when f:metadata section is processed, and fix DefaultFaceletContext.generateUniqueId(), so it generate the same id.