Já passei pelo mesmo problema ha algum tempo atrás e posto aqui a minha solução para JSF 2 usando prime faces. Tenho tb uma solução para JSF 1 usando richfaces, quem tiver interesse postar aqui que eu mando.
JSF 2.0 COM PRIME FACES.
[color=red]ANTES DE COMEÇAR É NECESSÁRIO DIZER QUE PARA A SOLUÇÃO ABAIXO FUNCIONAR VOCÊ TEM QUE NA CLASSES DE SUAS ENTIDADES VOCÊ SOBRESCREVER EXPLICITAMENTE OS MÉTODOS equals E hashcode. Para o exemplo abaixo funcionar a classe Cliente teria que sobrescrever o método equals e hashcode. Como você não vai ta fazendo isso em todas as suas classes de entidade, então basta criar uma superclasse abstrata de entidade e sobrescrever esses métodos lá e todas as entidades estendenrão desta. Por exemplo uma classe chamada Entidade que é abstrata.[/color]
[color=red]OUTRA COISA IMPORTANTE É QUE DA FORMA COMO O CONVERTER ESTA IMPLEMENTADO ABAIXO ELE ESPERA QUE O ITEM TENHA UM ATRIBUTO CHAMADO ‘id’ QUE É O IDENTIFICADOR NORMALMENTE USADO PARA ENTIDADES. CASO NO SEU PROJETO TENHA OUTRO PADRÃO FIQUE A VONTADE PARA MUDAR A PROPRIEDADE NO MÉTODO getIdByReflection DO CONVERTER.[/color]
Para tal é necessário colocar o converter abaixo:
import java.lang.reflect.Field;
import java.util.Collection;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
/**
*
* @author Victor Lindberg
*
*/
@FacesConverter("selectOneUsingObjectConverter")
public class SelectOneUsingObjectConverter implements Converter{
@Override
public Object getAsObject(FacesContext context,
UIComponent component, String value) {
if (value == null || value.equals(""))
return null;
try{
Long id = Long.valueOf(value);
Collection items = (Collection) component.getAttributes().get("items");
return findById(items, id);
}catch(Exception ex){
throw new ConverterException("Não foi possível aplicar conversão de item com valor ["+value+"] no componente ["+component.getId()+"]", ex);
}
}
@Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
if (value == null)
return "";
return getIdByReflection(value).toString();
}
private Object findById(Collection collection, Long idToFind){
for (Object obj : collection){
Long id = getIdByReflection(obj);
if (id == idToFind)
return obj;
}
return null;
}
private Long getIdByReflection(Object bean){
try{
Field idField = bean.getClass().getDeclaredField("id");
idField.setAccessible(true);
return (Long) idField.get(bean);
}catch(Exception ex){
throw new RuntimeException("Não foi possível obter a propriedade 'id' do item",ex);
}
}
}
Nosso MB:
[code]import java.util.List;
import javax.faces.bean.ManagedBean;
/**
*
*/
@ManagedBean(“clienteMB”)
public class ClienteMB {
private List<Cliente> listaClientes;
private Cliente clienteSelecionado;
public List<Cliente> getListaClientes() {
//carrega a lista de clientes
return listaClientes;
}
public void setListaClientes(List<Cliente> listaClientes) {
this.listaClientes = listaClientes;
}
public Cliente getClienteSelecionado() {
return clienteSelecionado;
}
public void setClienteSelecionado(Cliente clienteSelecionado) {
this.clienteSelecionado = clienteSelecionado;
}
}[/code]
Então para usar basta definir ele como sendo o converter e colocar explicitamente um atributo chamado ‘items’ na tag selectOneMenu como abaixo.
<p:selectOneMenu id="combo" value="#{clienteMB.clienteSelecionado}"
converter="selectOneUsingObjectConverter" items="#{clienteMB.listaClientes}">
<f:selectItem itemLabel="Selecione" itemValue="" />
<f:selectItems value="#{clienteMB.listaClientes}" var="cliente" itemLabel="#{cliente.nome}" itemValue="#{cliente}" />
</p:selectOneMenu>
Pronto, nossa combo do JSF ta funcionando belezinha.
É isso ai, qualquer coisa posta ae.
Victor Lindberg