O problema com esta "solução" é que os dados perduram. Exemplificando: imagine que você está implementando um caso de uso que mostra uma lista de entidades que obedecem às restrições impostas por filtros de busca cujos valores são determinados pelo usuário. O comportamento esperado é que, ao acessar a página, não se mostre nenhum valor, e após o usuário ordenar a busca, os elementos sejam obtidos e exibidos. Simples assim. Com a "solução" acima, isto ocorre na primeira vez que o usuário acessa esta página. Porém, dentro da mesma sessão, nas próximas vezes que o usuário acessar a página, ele irá automaticamente visualizar os dados da última busca que ele realizou.
Um pouco de pesquisa, na tentativa de manter o escopo como request, me levou à seguinte descrição de bug (que no final mostrou não ser um bug) - javaserverfaces:issue 69.
Conforme entendi, o problema é que no momento do processamento da fase Apply request values, o managed bean com os dados utilizados pela dataTable ainda não foi inicializado (ele somente será na fase Render response). Desta forma, a decodificação desta componente não funcionará como esperado, e tampouco a decodificação das componentes filhas (incluindo os commandLink's e commandButton's). Por isso, nenhum método de ação associado a estes elementos será executado.
Chegamos então à seguinte conclusão: nossa aplicação só funciona se usarmos escopo session. Mas isto é necessário somente para os dados a serem exibidos pelo dataTable. Com isto, sugiro a seguinte solução:
- Crie um managed bean (requestBean) em escopo request para gerenciar os dados não associados ao dataTable, e para gerenciar as ações da sua página
- Crie um managed bean (sessionBean) em escopo session somente para armazenar os dados exibidos pelo dataTable
- Você deve atribuir um valor vazio para os dados do sessionBean no construtor do requestBean, e com o resultado da busca, sempre que o método que realiza a busca em requestBean for executado
Surge aí outro problema. Como alterar os dados de sessionBean a partir do requestBean? Basta usar o seguinte código dentro do requestBean:
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().
createValueBinding("#{SessionBean.data}").setValue( context, newData );
Você pode reparar que o EL #{SessionBean.data} é igual ao EL que você usa no seu JSP associado ao atributo value da sua componente dataTable (h:dataTable).
É uma solução trabalhosa. Muito melhor seria se o JSF funcionasse de forma um pouco mais intuitiva. Mas nada é perfeito ...
Nenhum comentário:
Postar um comentário