Componentes JSF com problemas de atualização

olá,
desenvolvi alguns componentes em jsf 1.1 e agora estou usando-o em dois projetos. Em um projeto também jsf, o componente se comporta de maneira esquisita, ele é acessado uma primeira vez pelo usuário e todas as outras vezes em que é renderizado novamente ele renderiza o estado anterior.
Por exemplo, tem um componente que monta uma tabela dado alguns dados de entrada vindos de um banco. Mesmo com a mudança desses dados no banco, a próxima vez que esse componente é renderizado na mesma página, é mostrado o estado da vez anterior, ou seja, dados antigos.
Debugando, reparei que depois da primeira renderização, o o método setproperties não é mais chamado… isso é ruim. Olhando o ciclo de vida do jsf isso também não me parece correto. Testei com e sem formulários e também não obtive sucesso.

Alguem tem alguma idéia do problema? Já passou por algo parecido?

na verdade parece que tu que não entendeu muito bem :smiley:
o setProperties tem que criar bindValues e estes serão lidos todas as vezes que o componente for renderizado :smiley:

se foi isto que tu fez, ai tu vai ter que mostrar parte do código para vermos o que pode estar errado :smiley:

Sei que o setProperties liga as propriedades do meu componente à propriedades passadas pela Tag, que podem estar em ActionForm ou em um backing bean.
O problema acontece mesmo eu mudando os valores desses parâmetros do componente o resultado exibido é sempre o mesmo.
Debugando eu vejo o método setProperties sendo chamado na primeira renderização, é a única vez que ele é chamado. Da segunda em diante, mesmo quando os valores passados são diferentes (por exemplo um objeto resultSet) o componente renderiza os valores da primeira vez… entendeu?

Eu observei outra coisa…
quando eu entro numa página, o backing bean é inicializado (o método construtor é chamado), nele os valores de entrada para o componente são recuperados (de uma banco por exemplo).
Quando eu dou um refresh na página o método construtor não é chamado novamente.
Só consegui fazer o método construtor ser chamado novamente quando eu coloco mais de um <f:view> na página.

Muito estranho… será que eu estou usando errado o componente? O backing bean não deveria ser chamado novamente a cada carregamento da página?

posta aqui o teu setProperties, e também a parte do teu componente que le o valor pra eu ver o que pode estar errado.

setProperties

Dentro do componente tem um atributo chamado viaTable. Os valores são passados por esse atributo, ou seja, no projeto onde é usado esse componente é criado um objeto do tipo VIATable… isso dentro de um backing bean ou de um Action (se eu usar o componente jsf dentro de um projeto struts). Esse objeto criado é passado para o componente através de um atributo da tag chamado bind.

[code] protected void setProperties(UIComponent component)
{
super.setProperties(component);

    VIATableClass viaTable = (VIATableClass) component;
    Application app = getFacesContext().getApplication();
	
    if(id != null)
    {
        component.setId(id);
        viaTable.setId(id);
    }
	
    if(bind != null)
    {
        if (isValueReference(bind))
        {
            viaTable.setValueBinding("viaTable",app.createValueBinding(bind));


            FacesContext context = FacesContext.getCurrentInstance();
            app = context.getApplication();
            ValueBinding vb = app.createValueBinding(bind);
            //viaGraph.getSequenceItemList().setValueBinding("sequenceItemList", vb);
            Object v  = vb.getValue(context);
            viaTable.getAttributes().put("viaTable", v);
        }
    }

}[/code]

Mas tem outro lance, em um projeto jsf, quando eu dou refresh na página o construtor não é chamado depois da primeira vez. Isso não deveria acontecer??

não ddeveria não, quer dizer …
e você esta escrevendo componentes como se fossem tags simples MVC, componentes JSF são como componentes swing, então tu ta fazendo tudo errado :smiley:
a tag não tem que pegar o valor do parametro como tu ta fazendo em:
viaTable.getAttributes().put(“viaTable”, v);

o que tu tem que fazer é:
ValueBinding vb = context.getApplication().createValueBinding(value);
component.setValueBinding(propName, vb);

ou seja, tem que passar o value binding pro componente, e não o valor no momento em que é chamado o setProperties

e no getter do componente tu faz mais ou menos isto:
public String getEnabledOnUserRole()
{
if (_enabledOnUserRole != null) return _enabledOnUserRole;
ValueBinding vb = getValueBinding(“enabledOnUserRole”);
return vb != null ? _ComponentUtils.getStringValue(getFacesContext(), vb) : null;
}

ou seja, sempre usa o getter, e no getter sim tu pega o valor do binding que foi passado.

tradução, não é um problema do JSF, é um problema do teu componente como foi escrito :smiley:

da uma olhada no código dos componentes do tomahawk para pegar uns exemplos de como fazer componentes …

isto é devido ao late binding que os componentes JSF precisam ter …

Comecei a entender o late binding…
No setProperties quando vc faz o binding desse jeito
viaTable.getAttributes().put(“viaTable”, v);
o valor recuperado é uma cópia q sempre será usada nas próximas vezes. Mas quando vc faz
component.setValueBinding(propName, vb);
o valor é “linkado” com o objeto de onde está sendo usado o componente… como se fosse um único objeto que só o cliente altera. dai no getter sempre é recuperado esse binding… isso mesmo?

No seu código o que eu não entendi foi o
return vb != null ? _ComponentUtils.getStringValue(getFacesContext(), vb) : null;

Onde vc buscou esse _ComponentUtils??

Em vez de
return vb != null ? _ComponentUtils.getStringValue(getFacesContext(), vb) : null;
substitui por
return (VIATable) (vb != null ? vb.getValue(getFacesContext()) : null);

onde VIATable é o meu tipo.

Essa é a idéia?

Exatamente!!!