caso interessante. Per tutti, il seguente codice minimo riproduce questo:
facelet:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
>
<f:metadata>
<f:viewParam id="id" name="id" value="#{viewParamBean.id}"/>
</f:metadata>
<h:body>
<h:messages />
#{viewParamBean.id} <br/>
<h:form>
<h:inputText value="#{viewParamBean.text}" >
<f:validateLength minimum="2"/>
</h:inputText>
<h:commandButton value="test" action="#{viewParamBean.actionMethod}"/>
</h:form>
</h:body>
</html>
Bean:
@ManagedBean
@RequestScoped
public class ViewParamBean {
private long id;
private String text;
public void actionMethod() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Se si chiama il facelet con viewparam.xhtml?id=12
viene visualizzata la 12
sullo schermo. Se quindi inserisci qualcosa di valido, ad es. aaaaa
, l'ID sparirà dall'URL, ma continua a essere visualizzato sullo schermo (in possesso della natura di stato dei componenti dell'interfaccia utente).
Tuttavia ... come OP menzionato, non appena si verifica un errore di convalida (ad esempio, immettendo a
), l'ID verrà definitivamente perso. L'immissione di input validi in seguito non la riporterà indietro. Sembra quasi un bug, ma ho provato sia Mojarra 2.1 che Myfaces 2.1 ed entrambi hanno lo stesso comportamento.
Aggiornamento:
Dopo un po 'di ispezione, il problema sembra essere in questo metodo di `UIViewParameter' (Mojarra):
public void encodeAll(FacesContext context) throws IOException {
if (context == null) {
throw new NullPointerException();
}
// if there is a value expression, update view parameter w/ latest value after render
// QUESTION is it okay that a null string value may be suppressing the view parameter value?
// ANSWER: I'm not sure.
setSubmittedValue(getStringValue(context));
}
E poi più specificamente questo metodo:
public String getStringValue(FacesContext context) {
String result = null;
if (hasValueExpression()) {
result = getStringValueFromModel(context);
} else {
result = (null != rawValue) ? rawValue : (String) getValue();
}
return result;
}
Perché hasValueExpression()
è vero, proverà a ottenere il valore dal modello (il bean di supporto). Ma dal momento che questo bean è stato richiesto con scope, non avrà alcun valore per questa richiesta, poiché la validazione è appena fallita e quindi nessun valore è mai stato impostato.In effetti, il valore di stato di UIViewParameter
viene sovrascritto da qualunque cosa il backing bean ritorni come predefinito (tipicamente nullo, ma ovviamente dipende dal bean).
Una soluzione è quella di rendere il bean @ViewScoped
, che spesso è un ambito meglio comunque (suppongo si utilizza il parametro per ottenere un utente da un servizio, ed è forse inutile farlo più e più volte ad ogni postback) .
Un'altra alternativa è creare la propria versione di UIViewParameter
che non tenta di ottenere il valore dal modello se la convalida non è riuscita (come in pratica tutti gli altri componenti UIInput
).
stai usando 'includeViewParams = true' nella vostra azione presentare? – bluefoot
No, ma il mio gestore di azioni non viene chiamato: l'invio non riesce prima nella fase di convalida. – DenisGL