converter para selectOneMenu

356 views
Skip to first unread message

newmmax

unread,
Dec 11, 2010, 11:35:31 PM12/11/10
to javasf: JavaServer Faces Group
Meu código na view:

<h:selectOneMenu id="cidade"
value="#{clienteController.cliente.cidade}"
converter="SimpleIndexConverter">
<f:selectItems
value="#{clienteController.cidades}" var="cid" itemValue="#{cid}"
itemLabel="#{cid.cidade}" />
</h:selectOneMenu>

ta mostrando as cidades bonitinho, já na hora de salvar simplesmente
não da nada, nao faz nada.
to usando um SimpleIndexConverter já q a dica era que ele funcionasse
com boa parte das entidades (http://www.rponte.com.br/tag/
selectonemenu/) e minha entidade é simples demais, no entanto não da
erro nenhum e não faz alteração nenhuma.

o código do SimpleIndexConverter ficou assim:

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package beans;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;

@FacesConverter(value = "SimpleIndexConverter")
public class SimpleIndexConverter implements Converter {

private int index = -1;

/* (non-Javadoc)
* @see
javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext,
javax.faces.component.UIComponent, java.lang.String)
*/
@Override
public Object getAsObject(FacesContext ctx, UIComponent
component, String value) {

SelectItem selectedItem =
this.getSelectedItemByIndex(component, Integer.parseInt(value));
if (selectedItem != null)
return selectedItem.getValue();

return null;
}

/* (non-Javadoc)
* @see
javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext,
javax.faces.component.UIComponent, java.lang.Object)
*/
@Override
public String getAsString(FacesContext ctx, UIComponent
component, Object value) {
index++;
return String.valueOf(index);
}

/**
* Obtem o SelecItem de acordo com a opção selecionada pelo
usuário
*/
protected SelectItem getSelectedItemByIndex(UIComponent
component, int index) {

List<SelectItem> items = this.getSelectItems(component);
int size = items.size();

if (index > -1
&& size > index) {
return items.get(index);
}

return null;
}

protected List<SelectItem> getSelectItems(UIComponent
component) {

List<SelectItem> items = new ArrayList<SelectItem>();

int childCount = component.getChildCount();
if (childCount == 0)
return items;

List<UIComponent> children = component.getChildren();
for (UIComponent child : children) {
if (child instanceof UISelectItem) {
this.addSelectItem((UISelectItem) child, items);
} else if (child instanceof UISelectItems) {
this.addSelectItems((UISelectItems) child, items);
}
}

return items;
}

protected void addSelectItem(UISelectItem uiItem,
List<SelectItem> items) {

boolean isRendered = uiItem.isRendered();
if (!isRendered) {
items.add(null);
return;
}

Object value = uiItem.getValue();
SelectItem item;

if (value instanceof SelectItem) {
item = (SelectItem) value;
} else {
Object itemValue = uiItem.getItemValue();
String itemLabel = uiItem.getItemLabel();
// JSF throws a null pointer exception for null values
and labels,
// which is a serious problem at design-time.
item = new SelectItem(itemValue == null ? "" :
itemValue,
itemLabel == null ? "" : itemLabel, uiItem
.getItemDescription(),
uiItem.isItemDisabled());
}

items.add(item);
}

@SuppressWarnings("unchecked")
protected void addSelectItems(UISelectItems uiItems,
List<SelectItem> items) {

boolean isRendered = uiItems.isRendered();
if (!isRendered) {
items.add(null);
return;
}

Object value = uiItems.getValue();
if (value instanceof SelectItem) {
items.add((SelectItem) value);
} else if (value instanceof Object[]) {
Object[] array = (Object[]) value;
for (int i =0; i < array.length; i++) {
// TODO test - this section is untested
if (array[i] instanceof SelectItemGroup) {
resolveAndAddItems((SelectItemGroup) array[i],
items);
} else {
items.add((SelectItem) array[i]);
}
}
} else if (value instanceof Collection) {
Iterator<SelectItem> iter = ((Collection<SelectItem>)
value)
.iterator();
SelectItem item;
while (iter.hasNext()) {
item = iter.next();
if (item instanceof SelectItemGroup) {
resolveAndAddItems((SelectItemGroup) item,
items);
} else {
items.add(item);
}
}
} else if (value instanceof Map) {
for (Map.Entry<Object, Object> entry : ((Map<Object,
Object>) value).entrySet()) {
Object label = entry.getKey();
SelectItem item = new SelectItem(entry.getValue(),
label == null ? (String) null :
label.toString());
// TODO test - this section is untested
if (item instanceof SelectItemGroup) {
resolveAndAddItems((SelectItemGroup) item,
items);
} else {
items.add(item);
}
}
}
}

protected void resolveAndAddItems(SelectItemGroup group,
List<SelectItem> items) {
for (SelectItem item : group.getSelectItems()) {
if (item instanceof SelectItemGroup) {
resolveAndAddItems((SelectItemGroup) item, items);
} else {
items.add(item);
}
}
}

}


alguma dica pessoal ??

newmmax

unread,
Dec 12, 2010, 12:11:30 AM12/12/10
to javasf: JavaServer Faces Group
complementando, talvez possa ter algo errado aqui:


@Override
public int hashCode() {
int hash = 0;
hash += (idcidade != null ? idcidade.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
if (!(object instanceof Cidade)) {
return false;
}
Cidade other = (Cidade) object;
if ((this.idcidade == null && other.idcidade != null) ||
(this.idcidade != null && !this.idcidade.equals(other.idcidade))) {
return false;
}
return true;
}


Luiz Henrique Schutz

unread,
Dec 12, 2010, 2:19:14 PM12/12/10
to jav...@googlegroups.com
to usando um exemplo meu entao deve mudar as variaveis para as suas

No selectOneMenu eu fiz assim

<h:selectOneMenu id="Estado" required="true" value="#{cidadeMB.cidade.estado}">
       <f:selectItems value="#{cidadeMB.estados}" var="estado" itemLabel="#{estado.nome}" itemValue="#{estado}"/>
       <f:converter converterId="EstadoConverter"/>    
</h:selectOneMenu>

este EstadoConverter é uma classe que tenho que é assim

import javax.faces.component.UIComponent;

import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import Service.EstadoService;


@FacesConverter(value = "EstadoConverter" , forClass = EstadoConverter.class)
public class EstadoConverter implements Converter {
  @Override
 
  public Object getAsObject(FacesContext context, UIComponent component, String value) {
      if (value == null || value.length() == 0) {
          return null;
      }
      try {
          Long codigo = Long.valueOf(value);
          EstadoService est = new EstadoService();
          Estado object = est.getById(codigo);
            //busca pelo codigo da cidade no banco no lugar do model class usar a classe
          return object;

      } catch (NumberFormatException ex) {
          return null;

      }
  }

  @SuppressWarnings("unchecked")
  public String getAsString(FacesContext context, UIComponent component, Object value) {
      if (value == null) {
          return null;
      }
      Estado o = (Estado) value;
      //usar o nome da classe no lugar do ModelClass
      if (o.getCodigo() != null) {
          return o.getCodigo().toString();
      } else {
          return null;
      }
  }

}


e no teu model usa os equals e outras funcoes assim

@Override
    public boolean equals(Object obj){
        Estado outro = (Estado)obj;
        if(this == obj) return true;
        if(obj == null) return false;
        Estado that = (Estado)obj;
        return new EqualsBuilder().append(this.getNome(), outro.getNome()).isEquals();
    }


    @Override
    public int hashCode(){
        int obj1 = 0;
        int obj2 = 0;
        if(obj1==obj2) return obj1;
        if(obj2 == obj1) return obj2;
        return new HashCodeBuilder().append(this.getNome()).hashCode();
    }
   
    @Override
    public String toString(){
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE).append("Nome",this.getNome()).toString();
    }

    @Override
    public int compareTo(Estado o) {
        return new CompareToBuilder().append(this.getNome(),o.getNome()).toComparison();
    }

pra mim isto resolveu meu problema
no banco ele cadastra na tabela cidade o nome e o codigo do estado
espero ter ajudado

   }


--
Você recebeu esta mensagem por que é membro do  Javasf
http://groups.google.com/group/javasf

Conheça também o Java Brazil: http://groups.google.com/group/thejavabrazil



--
Luiz Henrique Schutz

newmmax

unread,
Dec 12, 2010, 5:31:53 PM12/12/10
to javasf: JavaServer Faces Group
obrigado Luiz Henrique,
o meu é mais simples ainda, pq a cidade e o estado ta na mesma tabela,
eu fiz um converter personalizado mesmo, mas parece que tem algo de
errado.

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans;

import dao.DaoFactory;
import entidades.Cidade;
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;

@FacesConverter(value = "cidadeConverter", forClass = Cidade.class)
public class cidadeConverter implements Converter {

@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1,
String arg2) throws ConverterException {
if (arg2 == null || arg2.length() == 0) {
return null;
}
Long id = new Long(arg2);
boolean hasTransaction =
DaoFactory.getInstance().hasTransaction();
if (hasTransaction == false) {
DaoFactory.getInstance().beginTransaction();
}

System.out.println("Convertendo a
porcaria:"+DaoFactory.getInstance().getCidadeDao().getCidadeByIdcidade(id).getIdcidade());
return
DaoFactory.getInstance().getCidadeDao().getCidadeByIdcidade(id);
}

@Override
public String getAsString(FacesContext facesContext, UIComponent
component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Cidade) {
Cidade o = (Cidade) object;
System.out.println("Convertendo a
porcaria:"+o.getCidade().toString());
return o.getIdcidade() == null ? "" :
o.getIdcidade().toString();
} else {
throw new IllegalArgumentException("object " + object + "
is of type " + object.getClass().getName() + "; expected type:
entidades.Cidade");
}
}
}



------------------------------------
a entidade:

package entidades;

import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
*
* @author Magno Max
*/
@Entity
@Table(name = "cidade")
public class Cidade implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Basic(optional = false)
private Long idcidade;
private String cidade;
private String estado;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "cidade",
fetch=FetchType.LAZY)
private List<Cliente> clienteList;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "cidade",
fetch=FetchType.LAZY)
private List<Livro> livroList;

public Cidade() {
}

public Cidade(Long idcidade) {
this.idcidade = idcidade;
}

public Long getIdcidade() {
return idcidade;
}

public void setIdcidade(Long idcidade) {
this.idcidade = idcidade;
}

public String getCidade() {
return cidade;
}

public void setCidade(String cidade) {
this.cidade = cidade;
}

public String getEstado() {
return estado;
}

public void setEstado(String estado) {
this.estado = estado;
}

public List<Cliente> getClienteList() {
return clienteList;
}

public void setClienteList(List<Cliente> clienteList) {
this.clienteList = clienteList;
}

public List<Livro> getLivroList() {
return livroList;
}

public void setLivroList(List<Livro> livroList) {
this.livroList = livroList;
}


@Override
public int hashCode() {
int hash = 0;
hash += (idcidade != null ? idcidade.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id
fields are not set
if (!(object instanceof Cidade)) {
return false;
}
Cidade other = (Cidade) object;
if ((this.idcidade == null && other.idcidade != null) ||
(this.idcidade != null && !this.idcidade.equals(other.idcidade))) {
return false;
}
return true;
}

}


-------------------------------------------------
o que acho estranho é que não dá erro, simplesmente não chega no meu
método de salvar

public void saveOrUpdate(ActionEvent actionEvent) {
boolean hasTransaction =
DaoFactory.getInstance().hasTransaction();
if (hasTransaction == false) {
DaoFactory.getInstance().beginTransaction();
}
if (getCliente() != null) {
System.out.println("Cidade salva: "+
cliente.getCidade().getCidade());

DaoFactory.getInstance().getClienteDao().insertOrUpdate(cliente);
try {
DaoFactory.getInstance().commit();
SessionUtil.addSuccessMessage("saveSuccess");
if (isInsert() == true) {
cliente = new Cliente();
}
} catch (Exception e) {
DaoFactory.getInstance().rollBack();
SessionUtil.addErrorMessage("saveFail");
} finally {
if (hasTransaction == false) {
DaoFactory.getInstance().close();
}

}
} else {
SessionUtil.addSuccessMessage("objectEmpty");
cliente = new Cliente();
}
}
------------------------------------------
coloquei uns println pra ver o q saia, mas nunca chega no meu médoto
de salvar, percebo que ele passa por dentro dos métodos de conversão
dentro de cidadeConverter e retorna os valores blz, mas não salva.

na view está assim agora:

<h:selectOneMenu id="cidade"
value="#{clienteController.cliente.cidade}"
converter="cidadeConverter" >
<f:selectItems
value="#{clienteController.cidades}" var="cid" itemValue="#{cid}"
itemLabel="#{cid.cidade}" />
</h:selectOneMenu>


esse negócio ja ta me prejudicando, se alguem puder me dar um help

Eduardo Nobre

unread,
Dec 13, 2010, 7:50:51 AM12/13/10
to jav...@googlegroups.com
Pessoal, será mesmo necessário usar um converter???
Nesta lista já foram postados exemplos que não precisam de converter.

segue um exemplo:


<h:selectOneMenu id="Estado" required="true" value="#{cidadeMB.cidade.estado.id}">
       <f:selectItems value="#{cidadeMB.estados}" var="estado" itemLabel="#{estado.nome}" itemValue="#{estado.id}"/>
</h:selectOneMenu>

note:  itemValue="#{estado.id}" e value="#{cidadeMB.cidade.estado.id}"
desta forma não necessita de converter, apenas o obejeto "cidadeMB.cidade.estado" deve pré-existir (ainda que seja com o id nulo, não o objeto)









   }


--
Você recebeu esta mensagem por que é membro do  Javasf
http://groups.google.com/group/javasf

Conheça também o Java Brazil: http://groups.google.com/group/thejavabrazil



--
Eduardo Nobre

Rafael Ponte

unread,
Dec 13, 2010, 11:25:51 AM12/13/10
to jav...@googlegroups.com
Eduardo,

De fato, não se faz necessário trabalhar diretamente com os objetos, algumas vezes é até melhor e mais simples sem eles mesmo. Contudo, por trabalharmos com um framework stateful, como Jsf, acaba valendo a pena usufruir deste recurso.

Mas enfim, não é regra. Se você está trabalhando direitinho apenas com IDs então bola pra frente.

2010/12/13 Eduardo Nobre <eduard...@gmail.com>



--
Rafael Ponte
http://www.rponte.com.br

Sérgio Fantin

unread,
Dec 13, 2010, 12:01:19 PM12/13/10
to jav...@googlegroups.com
Tá usando JSF 1.2 ou JSF 2?

2010/12/13 Rafael Ponte <rpo...@gmail.com>



--
Sérgio Fantin
http://serjaum.wordpress.com

Eduardo Nobre

unread,
Dec 13, 2010, 12:46:24 PM12/13/10
to jav...@googlegroups.com
JSF 2

Sérgio Fantin

unread,
Dec 14, 2010, 8:26:02 AM12/14/10
to jav...@googlegroups.com
Nas versões anteriores à versão 2.0 tínhamos que iterar sobre a nossa lista e retornar uma lista de SelectItem.
Com a versão 2.0 temos a propriedade "var", "itemLabel" e "itemValue". Então podemos retornar do método o tipo da sua lista, por ex: List<Pessoa> e converter através de um Converter. Fica mais ou menos assim: 

serviço
public List<Pessoa> getPessoas() {    
 
    return new DAO().list(new Pessoa());    
}

converter
@FacesConverter(value="converterPessoa", forClass=Pessoa.class)
public class ConverterPessoa implements Converter {

    @Override
    public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
        return DAO().getPessoa(Integer.valueOf(arg2));
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
        return String.valueOf(((Pessoa) arg2).getIdPessoa());
    }
}

xhtml
 <h:selectOneMenu value="#{pessoaMB.pessoa}">    
    <f:selectItems value="#{pessoaMB.pessoas}" var="pessoa" itemLabel="#{pessoa.descricao}" itemValue="#{pessoa}"/>    
    <f:converter converterId="converterPessoa"/>
</h:selectOneMenu>

Abraços...


2010/12/13 Eduardo Nobre <eduard...@gmail.com>
Reply all
Reply to author
Forward
0 new messages