2012-08-08 10 views
8

Ho costruire un componente personalizzato in JSF 2.0JSF 2 componenti personalizzati con Expression Language per valore di attributo non attivano il setter attributo

Il tag è simile al seguente:

<x:myTag id="1" name="AAA" /> 

La corrispondente classe java :

@FacesComponent("a.b.c.MyTag") 
public class UIMyTag extends UIInput { 

    private String name; 
    private String id; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 


    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Override 
    public void encodeBegin(FacesContext context) throws IOException { 
     ResponseWriter writer = context.getResponseWriter(); 
     logger.debug(getName()); //prints null for name="#{dummyBean.name}" 
           // and AAA for name="AAA" 
     logger.debug(getAttributes().get("name")); // always correct value 
    ... 
} 
    .... 

} 

Se uso

<x:myTag id="1" name="AAA" /> 

tutto funziona come previsto, ma quando uso EL per attributi myTag il metodo setName() non viene mai chiamato. Così, per,

<x:myTag id="#{dummyBean.id}" name="#{dummyBean.name}" /> 

Ho sempre trovato null per la name proprietà dentro il mio metodo encodeBegin. Dopo il debug, ho notato che il metodo setName non viene mai chiamato. Ho pensato che forse qualcosa riguardo a EL incasina le cose (e credo ancora che la ragione sia correlata a ciò), ma la cosa veramente strana è che la proprietà id funziona bene: il setter viene chiamato, e il valore è come previsto quando l'econding comincia.

Devo dire che se chiamo getAttributes().get("name") dal metodo encodeBegin ottengo il valore del nome corretto, ma sono incuriosito perché non funziona con getter e setter.

Qualche idea cosa manca al mio componente?

risposta

12

Questo comportamento è previsto e per specifica. I valori di attributo che sono espressioni di valore sono impostati da UIComponent#setValueExpression(). Si suppone che debbano essere valutati solo quando sono in realtà, di solito durante il tempo di rendering della vista.

L'attributo id (e binding) ha un trattamento speciale: è valutata durante il tempo di vista accumulo prima che è stato impostato, in modo che il setter "normale" sarebbe stato chiamato al posto del setValueExpression() (perché il rendering della vista incidente sarebbe altrimenti quando l'attributo id (o binding) valuta dinamicamente un valore diverso rispetto a quello che era durante il tempo di creazione della visualizzazione per qualche motivo).

È meglio delegare i getter/setter a UIComponent#getStateHelper() anziché a proprietà locali. Lo setValueExpression() finisce anche nello StateHelper (si noti che non chiama affatto il setter, basta chiamare il getter se si ha bisogno dei dati) e lo getAttributes() risolve anche i valori dallo StateHelper.

public String getName() { 
    return (String) getStateHelper().eval("name"); 
} 

public void setName(String name) { 
    getStateHelper().put("name", name); 
} 

Si noti che si può tranquillamente rimuovere le getId() e setId() metodi, perché sono già definied nella UIComponentBase superclasse che si sta estendendo da.

+0

Grazie per la risposta! Vorrei chiedere se devo implementare qualche metodo speciale per distinguere tra diversi tipi di valori di attributi all'interno del mio componente. (Ho capito che UIComponentBase lo gestisce da solo) E se sì, c'è una buona pratica per farlo ?! – RaresI

+0

No e in generale non dovresti nemmeno preoccupartene.Per ottenere il valore dell'attributo (valutato), basta richiamare il getter. – BalusC

Problemi correlati