Recentemente me deparei com um problema relativamente chato, o de ids duplicados.
O caso é que frequentemente é necessária a renderização sequencial de um mesmo JSP ou ainda um mesmo componente. Quanto não é atribuído um id único para um componente qualquer, o JSF o atribui dinâmicamente gerando algo como “_id05″.
Abordarei aqui as soluções para quando você está com dois tipos de problemas com ids duplicados, o fácil de resolver e o não tão fácil.
Duplicate component ID found in view : Este é o mais simples, basta atribuir ids únicos para cada componente e além disso, verificar se existem tags <f:verbatim> no JSP aonde o problema ocorre (por exemplo, um bloco de código javascript alocado dentro de um verbatim), caso exista, remova todas as ocorrências.
Duplicate id for a component: Este é um tanto mais complicado e geralmente ocorre quando se utiliza componentes customizados ou fora da RI. </p><p align=”justify”> Trata-se de um bug da especificação JSF RI 1.1 (não verifiquei sua ocorrência no JSF RI 1.2) em que a implementação do método UIComponentBase.getClientId() retorna explicita e diretamente o id do componente, o que faz com que qualquer implementação de getId() em alguma subclasse seja ignorada, ou seja, o id atribuído ao componente não é utilizado.</p>
A boa notícia é que isto pode ser facilmente resolvido utilizando algumas classes da Apache.
O que deve ser feito aqui é baixar a lista de classes abaixo (do KickJava) e fazer com que seu componente não mais extenda UIComponentBase do RI, mas sim o da Apache:
_AttachedListStateWrapper
_AttachedStateWrapper
_ComponentAttributesMap
_ComponentChildrenList
_ComponentFacetMap
_ComponentUtils
_FacetsAndChildrenIterator
_UIComponentBase
A mágica é feita na redefinição do UIComponentBase.getClientId().
Na nova classe, o seguinte trecho de código é a solução:
String id = getId();
if (id == null){
//Although this is an error prone side effect, we automatically create a new id
//just to be compatible to the RI
UIViewRoot viewRoot = context.getViewRoot();
if (viewRoot != null){
id = getId() + viewRoot.createUniqueId();
}else{
context.getExternalContext().log("ERROR: Cannot automatically create an id for component of type " + getClass().getName() + " because there is no viewRoot in the current facesContext!");
id = "ERROR";
}
//We remember that the id was null and log a warning down below
idWasNull = true;
}
A má notícia, é que embora o clientId do seu componente agora se comporte devidamente, ainda é provável a ocorrência do problema de id duplicado devido ao fato de que o id correto do componente também será re-renderizado, para isto basta realizar uma pequena modificação em UIComponentBase.getClientId() para que este sempre crie um id único (mantendo o id estipulado no componente):
// if (_clientId != null) return _clientId;
boolean idWasNull = false;
String id = null; //getId();
if (id == null){
//Although this is an error prone side effect, we automatically create a new id
//just to be compatible to the RI
UIViewRoot viewRoot = context.getViewRoot();
if (viewRoot != null){
id = getId() + viewRoot.createUniqueId();
}else{
context.getExternalContext().log("ERROR: Cannot automatically create an id for component of type " + getClass().getName() + " because there is no viewRoot in the current facesContext!");
id = "ERROR";
}
//We remember that the id was null and log a warning down below
idWasNull = true;
}
And it’s done!
Amigo,
Java é uma merda.
Como é que pode uma bosta de um bug desses?
Não dá nem pra fazer uma merda de um CRUD simples com essa porra.
Matheus,
este bug claramente não pertence ao domínio de problemas da linguagem Java, mas sim ao Java Server Faces, ou seja, ao framework.
Lamentavelmente é um bug muito chato e de solução não intuitiva, mas felizmente foi resolvido na versão 1.2 do JSF (a qual já foi liberada a muito tempo).
Portanto, esta solução está para ser aplicada a uma versão antiga do JSF, mas que em muitas aplicações continua em uso por algum motivo de compatibilidade.
Abraço!
Ve-se que o Matheus não consegur distinguir entra a ferramenta e a linguagem.