Boa tarde!
Tenho um tela de cadastro simples com um objeto Usuario com um relacionamento como Objeto Setor.
em um <h:selectOneMenu consigo carregar corretamente a lista:
<h:selectOneMenu value="#{usuarioBean.usuario.setor}" >
<f:selectItems value="#{usuarioBean.listaSetores}" />
</h:selectOneMenu>
porém no ato do cadastro recebo o seguinte erro:
Erro de conversão ao definir o valor ‘1’ para ‘null converter’.
No caso esse listaSetores são dados de banco de dados.
Tenho nesse mesmo form alguns ENUMs que funcionam perfeitamente.
O que fazer?
Posta ai o resto do código da sua view e o código do seu ManagedBean.
Ok. Segue os códigos solicitados.
manterUsuario.xhtml
<h:form id="form_pesquisa_usuario" rendered="#{usuarioBean.usuario.identificador == null}" style="width:672px; font: 12px 'TAHOMA'; text-align:justify;">
<p>Informe o identificador (NIP/Identidade Militar/Identidade Civil) do usuário para cadastro ou edição de dados.</p>
<h:panelGrid columns="3" id="grid_pesquisa_usuario">
<h:column>
<h:outputLabel value="Identificador: " for="identificador" id="label_identificador" />
</h:column>
<h:column>
<h:inputText value="#{usuarioBean.usuario.identificador}" id="identificador" />
</h:column>
<h:column>
<h:commandButton value="Pesquisar" action="#{usuarioBean.pesquisarUsuario}" id="pesquisar" />
</h:column>
</h:panelGrid>
</h:form>
<h:form id="form_cad_usuario" rendered="#{usuarioBean.usuario.identificador != null}">
<h:panelGrid columns="2" id="grid_cad_usuario" >
<h:column>
<h:outputLabel value="Identificador:" id="label_identificador" />
</h:column>
<h:column>
<h:inputText value="#{usuarioBean.usuario.identificador}" disabled="true" id="identificador" />
</h:column>
<h:column>
<h:outputLabel value="Vínculo: " id="label_vinculo" />
</h:column>
<h:column>
<h:selectOneMenu value="#{usuarioBean.usuario.vinculo}" id="vinculo">
<f:selectItems value="#{usuarioBean.vinculos}" id="vinculos"></f:selectItems>
</h:selectOneMenu>
</h:column>
<h:column>
<h:outputLabel value="Posto/Graduação:" for="posto_grad" id="label_posto_grad"/>
</h:column>
<h:column>
<h:selectOneMenu value="#{usuarioBean.usuario.postoGraduacao}" id="posto_grad">
<f:selectItems value="#{usuarioBean.listaPostoGraduacao}" id="lista_posto_grad" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:outputLabel value="OM:" for="om" id="label_om"/>
</h:column>
<h:column>
<h:selectOneMenu value="#{usuarioBean.usuario.organizacaoMilitar}" id="om">
<f:selectItems value="#{usuarioBean.listaOrganizacaoMilitar}" id="lista_om" ></f:selectItems>
</h:selectOneMenu>
</h:column>
<h:column>
<h:outputLabel value="Nome:" for="nome" id="label_nome"/>
</h:column>
<h:column>
<h:inputText value="#{usuarioBean.usuario.nmUsuario}" id="nome" size="40" />
</h:column>
<h:column>
<h:outputLabel value="Perfil:" for="perfil" id="label_perfil"/>
</h:column>
<h:column>
<h:selectOneMenu value="#{usuarioBean.usuario.perfil}" id="perfil">
<f:selectItems value="#{usuarioBean.perfis}" id="perfis"></f:selectItems>
</h:selectOneMenu>
</h:column>
<h:column>
<br />
<h:commandButton value="Finalizar" action="#{usuarioBean.cadastrarUsuario}" id="finalizar" />
</h:column>
<h:column />
</h:panelGrid>
</h:form>
<h:messages />
UsuarioBean
package br.mil.mar.com7dn.bean;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import br.mil.mar.com7dn.dao.BaseOrganizacaoMilitar;
import br.mil.mar.com7dn.dao.BasePostoGraduacao;
import br.mil.mar.com7dn.dao.BaseUsuario;
import br.mil.mar.com7dn.entity.OrganizacaoMilitar;
import br.mil.mar.com7dn.entity.Perfil;
import br.mil.mar.com7dn.entity.PostoGraduacao;
import br.mil.mar.com7dn.entity.Usuario;
import br.mil.mar.com7dn.entity.Vinculo;
@Model
public class UsuarioBean {
private Usuario usuario = new Usuario();
private List<SelectItem> vinculos = new ArrayList<SelectItem>();
private List<SelectItem> listaOrganizacaoMilitar = new ArrayList<SelectItem>();
private List<SelectItem> listaPostoGraduacao = new ArrayList<SelectItem>();
private List<SelectItem> perfis = new ArrayList<SelectItem>();
@Inject
private BaseUsuario baseUsuario;
@Inject
private BasePostoGraduacao basePostoGraduacao;
@Inject
private BaseOrganizacaoMilitar baseOrganizacaoMilitar;
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public List<SelectItem> getVinculos() {
return vinculos;
}
public void setVinculos(List<SelectItem> vinculos) {
this.vinculos = vinculos;
}
public List<SelectItem> getListaPostoGraduacao() {
return listaPostoGraduacao;
}
public void setListaPostoGraduacao(List<SelectItem> listaPostoGraduacao) {
this.listaPostoGraduacao = listaPostoGraduacao;
}
public List<SelectItem> getListaOrganizacaoMilitar() {
return listaOrganizacaoMilitar;
}
public void setListaOrganizacaoMilitar(List<SelectItem> listaOrganizacaoMilitar) {
this.listaOrganizacaoMilitar = listaOrganizacaoMilitar;
}
public List<SelectItem> getPerfis() {
return perfis;
}
public void setPerfis(List<SelectItem> perfis) {
this.perfis = perfis;
}
@PostConstruct
public void carregarFormularioUsuario(){
for(OrganizacaoMilitar om : baseOrganizacaoMilitar.getAll()) {
listaOrganizacaoMilitar.add(new SelectItem(om.getId(), om.getDsOrganizacaoMilitar()));
}
for(PostoGraduacao pG : basePostoGraduacao.getAll()) {
listaPostoGraduacao.add(new SelectItem(pG.getId(), pG.getDsPostoGraduacao()));
}
for(Vinculo vinculo : Vinculo.values()){
vinculos.add(new SelectItem(vinculo.name(), vinculo.toString()));
}
for(Perfil perfil : Perfil.values()){
perfis.add(new SelectItem(perfil.name(), perfil.toString()));
}
}
public String login() {
System.out.println(usuario.getIdentificador()+" "+usuario.getDsSenha());
if(usuario == null) {
return "index";
}else {
return "usuario/acessoUsuario";
}
}
public void pesquisarUsuario() {
usuario = baseUsuario.obterPeloIdentificador(usuario.getIdentificador());
}
public void cadastrarUsuario() {
System.out.println("TESTE");
baseUsuario.cadastrarUsuario(usuario);
}
}
Aguardo ajuda!
Édion TOrres
Foi mal kra mas, o trexo de código q vc mostrou no primeiro post não está presente nesse seu ultimo código. Agora eu não sei onde está o problema?
<h:column>
<h:outputLabel value="Posto/Graduação:" for="posto_grad" id="label_posto_grad"/>
</h:column>
<h:column>
<h:selectOneMenu value="#{usuarioBean.usuario.postoGraduacao}" id="posto_grad">
<f:selectItems value="#{usuarioBean.listaPostoGraduacao}" id="lista_posto_grad" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:outputLabel value="OM:" for="om" id="label_om"/>
</h:column>
<h:column>
<h:selectOneMenu value="#{usuarioBean.usuario.organizacaoMilitar}" id="om">
<f:selectItems value="#{usuarioBean.listaOrganizacaoMilitar}" id="lista_om" ></f:selectItems>
</h:selectOneMenu>
</h:column>
Aquela mensagem aparece para esse trecho de código.
Obrigado!
Me diz uma coisa kra, vc tem algum tipo de converter p/ os tipos PostoGraduacao e OrganizacaoMilitar? Supondo q eles são tipos do seu aplicativo.
São objetos do meu aplicativo e eu não tenho nenhum converter e nem sei o conceito muito menos como utilizar. rsrsr.
Se puder me passar algum material (indicar algum link) para eu aprender mais sobre isso.
Mas como devo proceder nesse caso?Como posso criar algum converter para resolver esse problema.
Cara, ai vão algumas dicas:
- Não use a anotação @Model p/ o seu ManagedBean. Ele não é model ele é controller. Use @Named no lugar;
- Não crie listas de SelectItems. A tag f:selectItems já suporta listas de qualquer tipo de objeto:
// no managed bean
public Lista<PostoGraduacao> getListaPostoGraduacao() {
// ...
}
// na view
<h:selectOneMenu ...>
<f:selectItems value="#{usuarioBean.listaPostoGraduacao} var="pg" itemValue="pg.id" itemLabel="pg.nome" />
</h:selectOneMenu>
- Crie um converter p/ os seus SelectMenus:
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;
@FacesConverter(value = "IndexedConverter")
public class IndexedConverter implements Converter {
private int index;
public Object getAsObject(FacesContext facesContext, UIComponent uicomp, String value) {
List<SelectItem> items = new ArrayList<SelectItem>();
List<UIComponent> uicompList = uicomp.getChildren();
for(UIComponent comp: uicompList){
if(comp instanceof UISelectItems){
items.addAll((List<SelectItem>) ((UISelectItems)comp).getValue());
}
}
return "-1".equals(value) ? null : items.get(Integer.valueOf(value)).getValue();
}
public String getAsString(FacesContext facesContext, UIComponent uicomp, Object entity) {
return entity == null ? "-1" : String.valueOf(index++);
}
}
Esse código não está perfeito (não meu, eu peguei emprestado de um amigo) mas deve funcionar. Se não funcionar é só postar ai q dou uma conferida nele. Ai na sua view é só se lembrar de adicionar o atributo “converter=“IndexedConverter”” nos seus h:selectOneMenu.
- Lembre-se de q vc precisa ter um hashCode e um equals p/ cada uma das suas entidades. Ou o selectOneMenu pode nunca aceitar a sua entidade como um valor válido.
Valeu pelas dicas. Creio que irá resolver meu problema.
Só uma observação, @Model é um estereótipo do WELD (RI CDI da JBOSS) que anota a classe como @Named e @RequestScoped.
Olha só:
[quote]Notice the controller bean is request-scoped and named. Since this combination is so common in
web applications, there’s a built-in annotation for it in CDI that we could have used as a shorthand.
When the (stereotype) annotation @Model is declared on a class, it creates a request-scoped
and named bean.
[/quote]
http://docs.jboss.org/weld/reference/1.1.0.Beta1/en-US/html/stereotypes.html#d0e4408
Sim mas a anotação @Model é um esteriotipo p/ classes de modelo. Anotar um controller com @Model funciona mas não faz muito sentido.
Veja se estou certo!
As classes Controller para utilização do JSF 2.0 tem que ser anotada com @ManagedBean certo? Para utilizar com CDI temos que mudar para @Named. Tudo isso para poder fazer binding no JSP/XHTML certo? Já que é comum utilizar @Named com @RequestScoped tem-se o estereótipo @Model (javax.enterprise.inject.Model), certo?
Se eu estiver errado me corrija pois foi assim que entendi tudo isso até agora! Rsrrs
Abraço!
Sim, vc está certo em dizer q anotar uma classe com @Model tem o mesmo efeito prático q anotar com @Named e @RequestScoped, mas isso não q é correto faze-lo. Segundo o padrão MVC, controllers e models tem finalidades diferentes na arquitetura de uma aplicação. Pense do seguinte modo, digamos q vc precise criar um classe p/ centralizar suas Queries e fazer a conversão dos dados relacionais p/ objetos do seu sistema (DAO). Vc daria à essa classe o nome de “Banana”? Na prática se vc chamar essa classe de “Banana” ela ainda vai funcionar mas pense no inferno q vai ser a vida do pobre coitado q tiver q dar manutenção no seu código tentando entender pq a droga da classe “Banana” parece fazer o trabalho de um DAO. Se ela vai funcionar como um DAO, não seria mais simples simplesmente chama-la de DAO?
Blz eu tinha entendido os conceitos. Mas eu vejo em palestras sobre CDI até mesmo do Pessoal da Caelum e na própria documentação do WELD, nos tutoriais e sempre utilizam esse conceito de @Model nos @managedBean. Isso porque para @Inject a classe Controller tem que estar anotado com @Named ao invés de @ManagedBean.
Mas se você está afirmando que é um erro utilizar @Model em classes Controller irei voltar a estudar novamente tudo porque creio que me enganei com alguma leitura.
Mas muito obrigado pela ajuda com o <h:selectItems e com os converter.
Abraço!
Na verdade edysnipes você é quem está correto! E nosso amigo dev.rafael se enganou (aliás, como ocorre com muitas pessoas devido a nomenclatura de @Model).
O @Model, neste caso, é apenas uma convenção de atalho que o pesoal do JBoss utiliza no Weld para facilitar a vida do desenvolvedor, já que a combinação @Named e @RequestScoped é uma das mais utilizadas. Convencionou-se, então, uní-las na anotação @Model.
Espero ter contribuido.