STRUTS - Combo box com struts e collections Orientado a Objeto

Bom Dia Galera, blz?

Entao fiquei o dia inteiro, procurando em Forums e vendo tutoriais e tentand resolver esse problema, mas aparentemente oq encontrei n é similar ao que estou fazendo!

Estou fazendo uns projetinhos básico para esquentar no Struts! Sou novo em desenvolvimento JAVA para WEB!

Bem lá vai!

Eu tenho a seguinte classe modelo Pessoa.java

package br.com.diogenes.hibernate.modelo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Pessoa {

	@Id
	@GeneratedValue
	@Column(name = "pes_id")
	private Long id;

	private String nome;

	private char ativo = 'F';

	@ManyToOne
	@JoinColumn(name = "estciv_id", nullable = true)
	private EstadoCivil estadocivil;

	private char sexo;

	public char getAtivo() {
		return ativo;
	}

	public void setAtivo(char ativo) {
		this.ativo = ativo;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public char getSexo() {
		return sexo;
	}

	public void setSexo(char sexo) {
		this.sexo = sexo;
	}

	public EstadoCivil getEstadocivil() {
		return estadocivil;
	}

	public void setEstadocivil(EstadoCivil estadocivil) {
		this.estadocivil = estadocivil;
	}

}

E a seguinte classe EstadoCivil.java

package br.com.diogenes.hibernate.modelo;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class EstadoCivil {

	@Id
	@GeneratedValue
	@Column(name = "estciv_id")
	private Long id;

	private String estadoCivil;

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "estadocivil")
	private List<Pessoa> pessoa;

	public String getEstadoCivil() {
		return estadoCivil;
	}

	public void setEstadoCivil(String estadoCivil) {
		this.estadoCivil = estadoCivil;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public List<Pessoa> getPessoa() {
		return pessoa;
	}

	public void setPessoa(List<Pessoa> pessoa) {
		this.pessoa = pessoa;
	}

}

Bom, a partir dai tenho uma classe DAO para cada uma dessas classes ambas com um método chamado “listaTudo()” que retorna um List de objetos daquele tipo!

Como podem ver é um relacionamento 1 pessoa tem um estado civil e 1 estado civil pode star em várias pessoas!
Usei essa estrutura com a classe SchemaExport e ela gerou a estrutura certinha no banco de dados, com as Fks corretas e os ids corretos!

Agora estou fazendo uma tela com struts de cadastro de Pessoas e gostaria de nesta tela incluir um “combo box - item de lista” com as tags do struts usando direto a List retornada pela classe DAO Referente à classe EstadoCivil!

Para tanto criei uma action que gera a List de EstadoCivil e adiciona no request e depois redireciona para o site de formulario!


public class NovaPessoaAction extends Action {

	public ActionForward execute(ActionMapping map, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {

		EstadoCivilDAO dao = new EstadoCivilDAO();

		List<EstadoCivil> listaEstadoCivil = dao.listaTudo(); 
		
		request.setAttribute("listaEstadoCivil", listaEstadoCivil);
		
		return map.findForward("ok");

	}	
	
}

Quando acesso a URL referente a essa action ela efetua corretamente e redireciona para a pagina novaPessoa.jsp


<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<html:html>

<head>

<title> Cadastro de Pessoa </title>

</head>

<html:errors />

<html:form action="/adicionaPessoa" focus="pessoa.nome">

Código: <html:text property="pessoa.id" disabled="true"/>
<br />
Nome: <html:text property="pessoa.nome" />
<br />
Ativo: <html:checkbox property="pessoa.ativo" value="T" alt="F" />
<br />
Sexo: <html:radio property="pessoa.sexo" value="M"> Masculino </html:radio> <html:radio property="pessoa.sexo" value="F"> Feminino </html:radio>
<br />
Estado Civil: 
<html:select property="pessoa.estadocivil">

<html:options collection="listaEstadoCivil" property="id" labelProperty="estadoCivil" />

</html:select>

<html:submit> Salvar </html:submit>

</html:form>



</html:html>

Até aqui tudo bem o site mostra o “combo box - list item” certinho sem problema algum!
O problema esta quando vou submeter os dados para salvar no banco de dados!

Ocorre o seguinte erro:

javax.servlet.ServletException: BeanUtils.populate
	org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:286)
	org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
	org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
java.lang.IllegalArgumentException: Cannot invoke br.com.diogenes.hibernate.modelo.Pessoa.setEstadocivil on bean class 'class br.com.diogenes.hibernate.modelo.Pessoa' - argument type mismatch - had objects of type "java.lang.String" but expected signature "br.com.diogenes.hibernate.modelo.EstadoCivil"
	org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:2181)
	org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:2141)
	org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1948)
	org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:2054)
	org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1015)
	org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:830)
	org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:433)
	org.apache.struts.util.RequestUtils.populate(RequestUtils.java:473)
	org.apache.struts.chain.commands.servlet.PopulateActionForm.populate(PopulateActionForm.java:50)
	org.apache.struts.chain.commands.AbstractPopulateActionForm.execute(AbstractPopulateActionForm.java:60)
	org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)
	org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
	org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:305)
	org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:191)
	org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)
	org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
	org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

O ActionForm referente a pagina de açao do novaPessoa.jsp é:


public class AdicionaPessoaForm extends ActionForm {

	private Pessoa pessoa = new Pessoa();

	public Pessoa getPessoa() {

		return this.pessoa;

	}

	@Override
	public void reset(ActionMapping map, HttpServletRequest req) {
		
		this.pessoa = new Pessoa();
		
		
	}

}

Pelo que vejo na linha do erro: java.lang.IllegalArgumentException: Cannot invoke br.com.diogenes.hibernate.modelo.Pessoa.setEstadocivil on bean class ‘class br.com.diogenes.hibernate.modelo.Pessoa’ - argument type mismatch - had objects of type “java.lang.String” but expected signature “br.com.diogenes.hibernate.modelo.EstadoCivil”

Acredito que de alguma forma ele nao esta entendendo que o valor do “combo box - list item” é um Objeto EstadoCivil esta passando como String!

Mas então como fazer o struts entender que aquele option tem como valor um objeto inteiro!

Na seguinte parte do código

Estado Civil:
<html:select property=“pessoa.estadocivil”>

<html:options collection=“listaEstadoCivil” property=“id” labelProperty=“estadoCivil” />

</html:select>

html:submit Salvar </html:submit>

</html:form>

Eu coloco a property como id que ai acaba sendo o getId da classe EstadoCivil, é isso que a tag envia para o servidor e ele n compreende como objeto? Se sim o que devo colocar na propriedade “property” da tag html:options para que ele entenda que é o objeto corrente da lista que deve ser enviada como parametro?
Ou devo modificar meu actionFormd e alguma forma para que ele entenda a classe EstadoCivil?
Ou existe uma melhor maneira de fazer isso que nao seja desse jeito?

Desde já agradeço!

Abraços!

Fala ae cara…

lá no FOrm esta faltando o set do objeto Pessoa.

abraços…

Entao na verdade nao, pois o struts da o getPessoa() para pegar o objeto pessoa e setar suas propriedades!
Mas de qq forma coloquei e testei e nao deu certo, mas valeu a sugestao!

Tem alguma outra idéia do que possa ser?

Entao galera andei, queimando a cabeça aqui mesmo e assim!
Tenho ctz q o pau é nessa linha de código

<html:select property="pessoa.estadocivil">   
  
<html:options collection="listaEstadoCivil" property="id" labelProperty="estadoCivil" />   
  
</html:select> 

Pq no caso a property da tag select esta referenciando uma outra classe dentro de pessoa e nao um atributo simples e a option esta retornando na property um id do tipo Long!

Como faço para fazer a property referenciar um objeto inteiro da lista?

Ou entao devo criar uma classe EstadoCivil dentro do ActionForm e mudar a property da tag select para essa estadoCivil.id e dentro da action que adicona atribuir a classe estadocivil para classe pessoa?

Sei que o tópico é antigo, mas pintou exatamente a mesma dúvida aqui.
Preciso referenciar um objeto no property mas pelo que pude perceber, o mesmo só envia String.
Tentei mesmo referenciando o objeto com um forEach e o erro é o mesmo, argument type mismatch

<html:select property="destino.departamento"> <c:forEach var="departamento" items="${departamentos}"> <html:option value="${departamento}">${departamento.nome}</html:option> </c:forEach> </html:select>

Por acaso vc conseguiu resolver diogenesvit?

Bom, pra ajudar a quem possa ter essa mesma dúvida, consegui achar uma solução.
Sendo que o ActionForm aceita apenas Strings o problema então não era tentar atribuir um objeto no property do select, e sim achar outra forma de obter o objeto a partir de uma String.
O que fiz foi criar um DynaActionForm e passar o id do meu objeto na property.
No JSP ficou assim:

<html:select property="departamento"> <html:options collection="departamentos" property="id" labelProperty="nome"></html:options> </html:select>
E é claro, mapear no struts-config.xml

<form-bean name="incluirDestinoDynaAction" type="org.apache.struts.action.DynaActionForm"> <form-property name="departamento" type="java.lang.String"/> <form-property name="nome" type="java.lang.String"/> </form-bean>