VRaptor 3 + DisplayTag + ClassePai/ClasseFilho

Olá pessoal

Estou usando vraptor e displaytag e no momento da minha listagem, tá gerando um erro que não estou conseguindo entender o porque.

Tenho a classe Restante, que possui duas outras classes como filho (Atividade e Contrato):

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

@Entity
public class Restante implements Serializable{

	@Id @GeneratedValue
	private Long cod_restante;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name="cod_contrato",insertable=true, updatable=true)
	@Fetch(FetchMode.JOIN)
	private Contrato contrato;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name="cod_atividade",insertable=true, updatable=true)
	@Fetch(FetchMode.JOIN)
	private Atividade atividade;
	
	@Column(precision=2)
	private double quantidade;
	
	@Column(nullable=false)
	@Temporal(TemporalType.DATE)
	private Date mes;

	public Long getCod() {
		return cod_restante;
	}

	public void setCod(Long codRestante) {
		cod_restante = codRestante;
	}

	public Contrato getContrato() {
		return contrato;
	}

	public void setContrato(Contrato contrato) {
		this.contrato = contrato;
	}

	public Atividade getAtividade() {
		return atividade;
	}

	public void setAtividade(Atividade atividade) {
		this.atividade = atividade;
	}

	public double getQuant() {
		return quantidade;
	}

	public void setQuant(double quantidade) {
		this.quantidade = quantidade;
	}

	public Date getMes() {
		return mes;
	}

	public void setMes(Date mes) {
		this.mes = mes;
	}
}

Controller:

@Resource
public class RestanteController {

	private Result result;
	private Restante restante;
	private RestanteDao dao = new RestanteDao();
	private Validator validator;
	private HttpSession session;
	
	private ContratoDao contratodao = new ContratoDao();
	private AtividadeDao atividadedao = new AtividadeDao();
	
	public RestanteController(Result result, Validator validator, HttpSession session){
		this.result = result;
		this.validator = validator;
		this.session = session;
	}
	
	public void insert(Restante restante){
		//SALVA
		dao.insert(restante);
		result.use(Results.logic()).redirectTo(getClass()).list();
	}
	
	@Path("/restante/edit/{restante.cod}")
	public void edit(Atividade atividade){
		this.restante = dao.search(restante.getCod());
		session.setAttribute("restanteEdit", this.restante);
		result.use(Results.logic()).redirectTo(getClass()).list();
	}
	
	@Path("/restante/delete/{restante.cod}")
	public void delete(Restante restante){
		dao.delete(restante);
		result.use(Results.logic()).redirectTo(getClass()).list();
	}

	public void list(){
		session.setAttribute("contratoCombo", contratodao.list());
		session.setAttribute("atividadeCombo",atividadedao.list());
		result.include("restanteList", new AtividadeDao().list()); 
	}

Na minha list, procuro chamar os get dos objetos filhos. Por exemplo: atividade.nome

<BODY onload="validaForm">

	<c:import url="/WEB-INF/cabecalho.html"/>
	
	<h1><fmt:message key="restante.titulo"/></h1><br>
	
	<!-- FORMULÁRIO -->
	<div id=sidebar>
	<form action="insert"
	      onSubmit="return validaForm();"
	      method="post">
		
		<input name="restante.cod" id="restante_cod" type="hidden" value="${restanteEdit.cod}"/> 
		
		<fmt:message key="restante.form.contrato"/><br>
		<select name="restante.contrato.cod" id="restante_contrato.cod">
			<option value=""></option>
			<c:forEach var="contrato" items="${contratoCombo}">
				<option value="${contrato.cod}"
						<c:if test="${restanteEdit.contrato.cod == contrato.cod}">selected="true"</c:if>>
						${contrato.nome} / ${contrato.uf}
				</option>
			</c:forEach>
		</select><br>
		<erro>
			<c:if test="${not empty errors[1].message}">
				<fmt:message key="${errors[1].message}"/>
			</c:if>	
		</erro><br>
		
		<fmt:message key="restante.form.atividade"/><br>
		<select name="restante.atividade.cod" id="restante_atividade.cod">
			<option value=""></option>
			<c:forEach var="atividade" items="${atividadeCombo}">
				<option value="${atividade.cod}"
						<c:if test="${restanteEdit.atividade.cod == atividade.cod}">selected="true"</c:if>>
						${atividade.nome} / ${atividade.uf}
				</option>
			</c:forEach>
		</select><br>
		<erro>
			<c:if test="${not empty errors[2].message}">
				<fmt:message key="${errors[2].message}"/>
			</c:if>	
		</erro><br>
		
		<fmt:message key="restante.form.quant"/><br>
		<input name="restante.quant" id="restante_quant" value="${restanteEdit.quant}"
			   onKeyPress="return validaChars(event,this);"
		       onKeyDown="return backspaceChars(event,this);"/><br>
		<erro>
			<c:if test="${not empty errors[3].message}">
				<fmt:message key="${errors[3].message}"/>
			</c:if>	
		</erro><br>
		
		<fmt:message key="restante.form.mes"/><br>
		<input name="restante.mes" id="restante_mes" value="${restanteEdit.mes}"/><br>
		<erro>
			<c:if test="${not empty errors[4].message}">
				<fmt:message key="${errors[4].message}"/>
			</c:if>	
		</erro><br>
		
		<button type="submit"><fmt:message key="botao.salvar"/></button>  
			
	</form>
	</div>
	
	<!-- DISPLAY -->
	<div id=content>
	<!--  setando título no head da tabela -->
	<display:table id="restante" name="${restanteList}" requestURI="/restante/list" 
	    sort="list" defaultsort="0" export="true" >
		<display:column title="Cod" property="cod" sortable="true" />
		<display:column title="Contrato" property="contrato.nome" sortable="true" />
		<display:column title="Cc" property="contrato.cc" sortable="true" />
		<display:column title="Projeto" property="contrato.projeto" sortable="true" />
		<display:column title="Uf" property="contrato.uf" sortable="true" />
		<display:column title="Atividade" property="atividade.nome" sortable="true" />
		<display:column title="Quant" property="quant" sortable="true" />
		<display:column title="Mês" property="mes" sortable="true" />
		<display:column>
			<a href="edit/${restante.cod}"><fmt:message key="link.editar"/></a>
		</display:column>
		<display:column>
			<a href="delete/${restante.cod}"><fmt:message key="link.remover"/></a>
		</display:column>
	</display:table>
	</div>
	
</BODY>

O form está funcionando. Mas a listagem não. Não sei pq ele está procurando o objeto/propriedade “contrato” dentro da classe “atividade”:

14/12/2009 11:13:10 org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.NoSuchMethodException: Unknown property 'contrato' on class 'class bsr.hibernate.tabela.Atividade'
	at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1322)
	at org.apache.commons.beanutils.PropertyUtils.getSimpleProperty(PropertyUtils.java:611)
	at org.displaytag.util.LookupUtil.getProperty(LookupUtil.java:237)
	at org.displaytag.util.LookupUtil.getBeanProperty(LookupUtil.java:129)
	at org.displaytag.model.Column.getValue(Column.java:124)
	at org.displaytag.model.Column.createChoppedAndLinkedValue(Column.java:201)
	at org.displaytag.model.Column.initialize(Column.java:178)
	at org.displaytag.render.TableWriterTemplate.writeTableBody(TableWriterTemplate.java:313)
	at org.displaytag.render.TableWriterTemplate.writeTable(TableWriterTemplate.java:138)
	at org.displaytag.render.HtmlTableWriter.writeTable(HtmlTableWriter.java:734)
	at org.displaytag.tags.TableTag.writeHTMLData(TableTag.java:1647)
	at org.displaytag.tags.TableTag.doEndTag(TableTag.java:1300)
	at org.apache.jsp.WEB_002dINF.jsp.restante.list_jsp._jspService(list_jsp.java:511)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at br.com.caelum.vraptor.core.DefaultStaticContentHandler.deferProcessingToContainer(DefaultStaticContentHandler.java:56)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:90)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
	at br.com.caelum.vraptor.view.DefaultPageResult.forward(DefaultPageResult.java:75)
	at br.com.caelum.vraptor.extra.ForwardToDefaultViewInterceptor.intercept(ForwardToDefaultViewInterceptor.java:64)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.download.DownloadInterceptor.intercept(DownloadInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.OutjectResult.intercept(OutjectResult.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:74)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:93)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:54)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:51)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:58)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:58)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.core.URLParameterExtractorInterceptor.intercept(URLParameterExtractorInterceptor.java:45)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:70)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:57)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:71)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:71)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:99)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:37)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:97)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
	at java.lang.Thread.run(Unknown Source)

Eu dei uma pesquisada aqui no fórum mesmo em assuntos envolvendo displaytag e vraptor3 mas não achei um caminho pro meu problema.
Se puderem em ajudar, agradeço.

vc tá listando Atividades, mas acho que vc queria listar Restantes, não?

é necessário colocar atributos direto na sessão mesmo?

Sim Lucas

Além dos atributos cod,quant e mês, Restante tbm possui mais dois atributos do tipo: Contrato e Atividade, que são classes minhas.

Dentro dessas classe Contrato eu possuo: getNome, getCc, getProjeto, getUf
E dentro de Atividade eu possuo> getNome

O que eu to tentando fazer é um getContrato().getNome…

<display:column title="Contrato" property="contrato.nome" sortable="true" />  
<display:column title="Cc" property="contrato.cc" sortable="true" />  
<display:column title="Projeto" property="contrato.projeto" sortable="true" />  
<display:column title="Uf" property="contrato.uf" sortable="true" />  
<display:column title="Atividade" property="atividade.nome" sortable="true" />  

O mesmo quero fazer com Atividade, q vc perguntou.

Com relação aos atributos na sessão. Bom, dos três, um é para o Edit e os outros dois para preencher os ComboBox(Select) do formulário. Não tem influência no displaytag.

Valeu!!!

repare na linha

 result.include("restanteList", new AtividadeDao().list()); 

Vc tá listando Atividades! não existe campo contrato em atividades, só nome…

vc deveria mudar pra algo do tipo:

 result.include("restanteList", restanteDao.list()); 

Pq vc não pode fazer result.include nesses caras que vc incluiu na sessão? (ao invés de session.setAttribute)

Nooooooossa Lucas, haha, não tinha visto.
Isso q dá fazer um ctrl+c ctrl+v no controller de atividade, huahua

Valeu mesmo. Não tinha enxergado isso na primeira vez que você falou.