2012-08-08 13 views
8

Tengo construir un componente personalizado en JSF 2.0JSF 2 componentes personalizados que tienen lenguaje de expresión para el valor del atributo no activan el colocador atributo

La etiqueta se ve así:

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

la clase Java correspondiente :

@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 
    ... 
} 
    .... 

} 

Si uso

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

todo funciona como se esperaba, pero cuando uso EL para los atributos myTag el método setName() nunca se llama. Así que para,

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

Siempre me null para la propiedad name dentro de mi método encodeBegin. Después de la depuración, me he dado cuenta de que nunca se llama al método setName. Pensé que tal vez algo relacionado con EL estropea las cosas (y sigo creyendo que la razón está relacionada con eso), pero lo que es realmente extraño es que la propiedad id funciona bien: se llama al colocador y el valor es el esperado cuando el proceso comienza.

Tengo que mencionar que si llamo al getAttributes().get("name") desde el método encodeBegin, obtengo el valor de nombre correcto, pero estoy intrigado porque no funciona con getter y setter.

¿Alguna idea de lo que falta en mi componente?

Respuesta

12

Este comportamiento es esperado y por especificación. Los valores de atributo que son expresiones de valor se establecen en UIComponent#setValueExpression(). Se supone que deben evaluarse solo cuando se usan realmente, generalmente durante el tiempo de visualización de la vista.

El atributo id (y binding) tiene un tratamiento especial: se evaluó durante el tiempo de vista acumulación antes que ha sido establecido, por lo que el colocador "normal" sería llamado en lugar del setValueExpression() (debido a la representación de la vista de otro modo accidente cuando el atributo id (o binding) evalúa dinámicamente a un valor diferente de lo que era durante el tiempo de compilación de la vista por algún motivo).

Mejor es delegar los getters/setters a UIComponent#getStateHelper() en lugar de a las propiedades locales. El setValueExpression() finalmente también termina en el StateHelper (tenga en cuenta que no llama al setter en absoluto, solo llame al captador si necesita los datos) y el getAttributes() también resuelve los valores del StateHelper.

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

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

Tenga en cuenta que con seguridad puede eliminar los métodos getId() y setId(), debido a que ya están en el definied UIComponentBase superclase el que se está extendiendo a partir.

+0

¡Gracias por la respuesta! Me gustaría preguntar si tengo que implementar algún método especial para distinguir entre diferentes tipos de valores de atributos dentro de mi componente. (Entendí que UIComponentBase lo maneja por sí mismo) Y si es así, ¿existe una mejor práctica para hacerlo? – RaresI

+0

No y en general tampoco debería preocuparse por eso.Para obtener el valor del atributo (evaluado), solo invoque el getter. – BalusC

Cuestiones relacionadas