Olá pessoal, eu preciso fazer uma tela de cadastro de matrícula, onde entro com informações iniciais do aluno e seleciono o Curso que ele vai fazer (cursos que já estão cadastrados no sistema). Eu to conseguindo puxar os dados do banco e mostrar no SelectOneMenu mas quando eu clico em salvar, não aparece nenhum erro, o SelectOneMenu apenas fica contornado em vermelho e nada é gravado no banco… Aalguém poderia me ajudar? vou mostrar umas partes dos códigos…
public List<SelectItem> getSelectCursos(){
List<Curso> list = daoCurso.listar();
List<SelectItem> itens = new ArrayList<SelectItem>(list.size());
for(Curso c : list){
itens.add(new SelectItem(c.getCodCurso(), c.getNomeCurso()));
}
return itens;
}
Aluno.class
//bi-directional many-to-one association to Curso
@ManyToOne
@JoinColumn(name="codCursoAluno")
private Curso curso;
MBAluno
public void save() throws ParseException{
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date data = new Date(format.parse(dtNasc).getTime());
beanAluno.setDtNascAluno(data);
daoAluno.save(beanAluno);
dtNasc = null;
}
Cara é o seguinte, se a classe Aluno possui relacionamento com a classe Curso logo vc tem que salvar o ID da tabela curso na tabela aluno,
e não o nome do curso desta forma:
fiz do jeito que você disse…e quando clico em Salvar, aparece uma mensagem de validação no SelectOneMenu dizendo “Erro de conversão ao definir o valor ‘10’ para ‘null Converter’.” Tem idéia do q seja? se o erro for no converter, me ajuda a arrumar ele por favor…
Eu uso um converter que você não precisa ir no banco para buscar a lista, eu acho bem mais simples e ele é genérico, para toda a aplicacões você só usa ele. Como está abaixo , você precisa colocar mais um atributo chamado “items” e o converter recebe essa lista lá através dessa linha de código: "component.getAttributes().get(“items”); " (que fica no converter).
@FacesConverter("objectConverter")
public class ObjectConverter implements Converter {
@Override // Metodo que é chamado na inicialização do converter que pega os objetos da Lista e pega os ids deles através de reflexão e retorna esses ids em forma de String*/
public String getAsString(FacesContext context, UIComponent component,Object value) {
// Primeira linha em branco da combo caso exista,
// Aqui simulamos que o id desse campo em branco seja "-1"
if (value == "") {
return "-1";
}
// Quando precisa renderizar uma combo com valor ainda não adquirido (null).
// que é renderizada antes mesmo que um objeto seja selecionado.
if(getIdByReflection(value) == null){
return "-1";
}
// Retorna o id como Long, adquirido atraves de reflexão
return getIdByReflection(value).toString();
}
@Override // Quando eu seleciono um arquivo na combo por exemplo, ele pega o objeto e seta o valor do componente.
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (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);
}
}
/** Retorna o objeto pelo id */
private Object findById(Collection collection, Long idToFind) {
Object object = null;
for (Object obj : collection) {
Long id = getIdByReflection(obj);
if (id.equals(idToFind)) {
object = obj;
break;
}
}
return object;
}
private Long getIdByReflection(Object bean) {
try {
// Pega o Id do objeto
Field idField = bean.getClass().getDeclaredField("id");
idField.setAccessible(true);
return (Long) idField.get(bean);
} catch (Exception ex) {
throw new ConverterException("Não foi possível obter a propriedade 'id' do item", ex);
}
}
}
Eu não estou dizendo que o outro exemplo do colega esteja errado, é só outra maneira de fazer a mesma coisa.
javax.faces.convert.ConverterException: Não foi possível obter a propriedade 'id' do item
at converter.ConverterCurso.getIdByReflection(ConverterCurso.java:84)
at converter.ConverterCurso.getAsString(ConverterCurso.java:34)
at org.primefaces.renderkit.InputRenderer.getOptionAsString(InputRenderer.java:162)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeOption(SelectOneMenuRenderer.java:347)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeSelectItems(SelectOneMenuRenderer.java:333)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeInput(SelectOneMenuRenderer.java:114)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeMarkup(SelectOneMenuRenderer.java:91)
at org.primefaces.component.selectonemenu.SelectOneMenuRenderer.encodeEnd(SelectOneMenuRenderer.java:65)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:879)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1650)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1646)
at org.primefaces.component.panelgrid.PanelGridRenderer.encodeRow(PanelGridRenderer.java:143)
at org.primefaces.component.panelgrid.PanelGridRenderer.encodeStaticBody(PanelGridRenderer.java:107)
at org.primefaces.component.panelgrid.PanelGridRenderer.encodeBody(PanelGridRenderer.java:63)
at org.primefaces.component.panelgrid.PanelGridRenderer.encodeEnd(PanelGridRenderer.java:49)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:879)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1650)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:164)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:849)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1643)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1646)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:389)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:127)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:117)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:135)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:309)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NoSuchFieldException: codCurso
at java.lang.Class.getDeclaredField(Unknown Source)
at converter.ConverterCurso.getIdByReflection(ConverterCurso.java:80)
... 42 more
pra nao precisar mudar o banco, eu não posso apenas mudar de Long pra Integer lá no converter? outra coisa… vc passa uma lista de selectItem ou lista lah no SelectOneMenu? Obrigado!
É passado ali uma lista de Object, vc pode ver que na linha 35 do converter ele seta uma Collection com essa lista e depois na linha 50 ele interage essa Collection em um for do tipo Object.
Eu acredito que não dê problema mudar no converter todas as Referencias de Long para Integer, tenta lá e depois avisa se deu certo.
Fiz as modificações e continua dando o mesmo erro :
“Caused by: java.lang.NoSuchFieldException: id
at java.lang.Class.getDeclaredField(Unknown Source)
at converter.ConverterCurso.getIdByReflection(ConverterCurso.java:80)
… 42 more”
Não teria que trocar o “id” aqui nessa linha? Field idField = bean.getClass().getDeclaredField(“id”);
não sei oq tenho que colocar no lugar… “codCurso” ??
Dando uma olhada no seu código eu estou vendo que o " #{MBCurso.selectCursos} " continua indo sem id, porque no método getSelectCursos() você só seta o CodCursos e NomeCursos como consta na linha 5 do seu MBCurso (" itens.add(new SelectItem(c.getCodCurso(), c.getNomeCurso())); "), e o Converter precisa desse id.
Debuga o Converter e vê exatamente o que está acontecendo.
… nesse “list” todos os itens estão vindo com esse id populado ?
Posta aqui depois esse seu método “daoCurso.listar()” .
Caso essa classe não tenha um atributo id crie um para facilitar no uso do converter.
private Long id;
//getters e setters
… e popule ele no método listar.
Outra coisa, porque vc criou uma classe “SelectItem” , ao inves de usar o atributo “list” do retorno do método listar. Você pode usar esse “list” direto para listar os itens da combo.
Entendi Gustavo…realmente nao tem esse atributo na minha classe Curso. Tem o atributo codCurso. Já experimentei passar “codCurso” como argumento do “getDeclaredField()” mas acontece o msmo erro.
Cara, desculpa. Vendo o seu código de novo, eu achei o erro … vc está passando no “itemValue” o id, sendo que nesse caso usando o converter, vc tem que passar o objeto mesmo . Pois o converter está esperando um objeto com id ou codCurso , não um objeto Long Id cru.
To quase desistindo… vou mostrar meu código novamente pq fiz algumas alterações e agora pelo menos ta aparecendo uma mensagem de erro nova. No SelectOneMenu aparece essa mensagem quando tento salvar: “{0}: Ocorreu um erro de conversão.” O problema é q não aparece nenhuma stacktrace.
//bi-directional many-to-one association to Curso @ManyToOne @JoinColumn(name=“codCursoAluno”)
private Curso curso;
…[/code]
Curso
.....
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int codCurso;
.......
ConverterCurso
[code]@FacesConverter(value=“cursoConverter”, forClass=Curso.class)
public class ConverterCurso implements Converter{
@Override // Metodo que é chamado na inicialização do converter que pega os objetos da Lista e pega os ids deles através de reflexão e retorna esses ids em forma de String*/
public String getAsString(FacesContext context, UIComponent component,Object value) {
// Primeira linha em branco da combo caso exista,
// Aqui simulamos que o id desse campo em branco seja "-1"
if (value == "") {
return "-1";
}
// Quando precisa renderizar uma combo com valor ainda não adquirido (null).
// que é renderizada antes mesmo que um objeto seja selecionado.
if(getIdByReflection(value) == null){
return "-1";
}
// Retorna o id como Long, adquirido atraves de reflexão
return getIdByReflection(value).toString();
}
@Override // Quando eu seleciono um arquivo na combo por exemplo, ele pega o objeto e seta o valor do componente.
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value.equals("")) {
return null;
}
try {
Integer id = Integer.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);
}
}
/** Retorna o objeto pelo id */
private Object findById(Collection collection, Integer idToFind) {
Object object = null;
for (Object obj : collection) {
Integer id = getIdByReflection(obj);
if (id.equals(idToFind)) {
object = obj;
break;
}
}
return object;
}
private Integer getIdByReflection(Object bean) {
try {
// Pega o Id do objeto
Field idField = bean.getClass().getDeclaredField("codCurso");
idField.setAccessible(true);
return (Integer) idField.get(bean);
} catch (Exception ex) {
throw new ConverterException("Não foi possível obter a propriedade 'id' do item", ex);
}
}
}[/code]
método save do MBAluno
[code]…
public void save() throws ParseException{
SimpleDateFormat format = new SimpleDateFormat(“dd/MM/yyyy”);
Date data = new Date(format.parse(dtNasc).getTime());
beanAluno.setDtNascAluno(data);
daoAluno.save(beanAluno);
dtNasc = null;
}....[/code]
Desculpa encher o saco com esse problema… mas preciso resolver isso pra seguir em frente com o meu projeto de Engenharia de Software.
Obrigado
Você esqueceu novamente de colocar o atributo “items” no seu componente selectOneMenu como mostrei lá em cima, você precisa colocar esse atributo com a lista que popula o componente para que o converter receba essa lista como mostra na linha 33 do converter.