2012-08-08 4 views
8

ich eine benutzerdefinierte Komponente in JSF bauen 2.0JSF 2 Benutzerdefinierte Komponenten Expression Language für Attribut-Wert auslösen nicht das Attribut Setter

Der Tag sieht wie folgt aus:

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

Die entsprechende Java-Klasse :

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

} 

Wenn ich

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

alles funktioniert wie erwartet, aber wenn ich EL für myTag Attribute verwende, wird die setName() Methode nie aufgerufen. Also für,

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

Ich bekomme immer null für die name Eigenschaft in meiner encodeBegin Methode. Nach dem Debuggen ist mir aufgefallen, dass die Methode setName nie aufgerufen wird. Ich dachte, dass etwas in Bezug auf EL Dinge vermasselt (und ich glaube immer noch, dass der Grund damit zusammenhängt), aber was wirklich seltsam ist, ist dass die id Eigenschaft gut funktioniert: der Setter wird aufgerufen, und der Wert ist wie erwartet beginnt.

Ich muss erwähnen, dass, wenn ich getAttributes().get("name") von der encodeBegin Methode aufrufen ich den richtigen Namen Wert, aber ich bin fasziniert, warum es nicht mit Getter und Setter funktioniert.

Irgendwelche Ideen, was zu meiner Komponente fehlt?

Antwort

12

Dieses Verhalten wird erwartet und nach Spezifikation. Attributwerte, die Wertausdrücke sind, werden durch UIComponent#setValueExpression() festgelegt. Sie sollen nämlich nur dann ausgewertet werden, wenn sie wirklich verwendet haben, normalerweise während der Renderzeit.

Das id (und binding) Attribut hat eine besondere Behandlung: es während Ansicht Kompilierzeit vor ausgewertet ist es gesetzt worden ist, so dass die „normale“ Setter würde anstelle der setValueExpression() aufgerufen werden (weil es sonst der Ansicht Rendering-Absturz wenn das id (oder binding) Attribut aus irgendeinem Grund dynamisch einen anderen Wert ausgibt als es während der Aufbauzeit der Ansicht war.

Besser ist es, die Getter/Setter zu UIComponent#getStateHelper() anstatt zu lokalen Eigenschaften zu delegieren. Die setValueExpression() endet letztlich auch in der StateHelper (beachten Sie, dass es den Setter überhaupt nicht aufrufen; rufen Sie einfach den Getter, wenn Sie die Daten benötigen) und die getAttributes() löst auch die Werte von StateHelper.

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

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

Beachten Sie, dass Sie sicher die getId() und setId() Methoden entfernen können, weil sie bereits in dem UIComponentBase Super definiertem, die Sie von sind erstrecken.

+0

Danke für die Antwort! Ich möchte fragen, ob ich eine spezielle Methode implementieren muss, um zwischen verschiedenen Typen von Attributwerten innerhalb meiner Komponente zu unterscheiden. (Ich habe verstanden, dass UIComponentBase es eigenständig handhabt) Und wenn ja, gibt es eine Best Practice, das zu tun ?! – RaresI

+0

Nein, und Sie sollten sich auch nicht darum kümmern.Um den (bewerteten) Attributwert zu erhalten, rufen Sie einfach den Getter auf. – BalusC

Verwandte Themen