Problema com vraptor 3 no GAE

Olá pessoal não sei se isso é um bug do vraptor no GAE ou algo similar .

Estou utilizando um controller que popula no construtor um atributo que é um objeto da sessão ;

quando o método utiliza um forward ou redirect ele lança a exception abaixo :

Caused by: br.com.caelum.vraptor.proxy.ProxyCreationException: Tried to instantiate type: class br.com.jslsolucoes.erbuss.site.controllers.EmpresaProdutoController 1 times, but none of the attempts worked. The exceptions are: [net.sf.cglib.core.CodeGenerationException: java.lang.NullPointerException-->null]
package br.com.jslsolucoes.erbuss.site.controllers;

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.poi.util.IOUtils;

import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.interceptor.multipart.UploadedFile;
import br.com.caelum.vraptor.view.Results;
import br.com.jslsolucoes.erbuss.site.annotations.Paginated;
import br.com.jslsolucoes.erbuss.site.daos.EmpresaAtividadeDao;
import br.com.jslsolucoes.erbuss.site.daos.EmpresaProdutoDao;
import br.com.jslsolucoes.erbuss.site.daos.EmpresaProdutoFotoDao;
import br.com.jslsolucoes.erbuss.site.daos.ProdutoDao;
import br.com.jslsolucoes.erbuss.site.models.Empresa;
import br.com.jslsolucoes.erbuss.site.models.EmpresaProduto;
import br.com.jslsolucoes.erbuss.site.models.EmpresaProdutoFoto;
import br.com.jslsolucoes.erbuss.site.util.view.VraptorViewUtil;


@Resource
@Path("produto")
public class EmpresaProdutoController {
	
	private EmpresaProdutoDao daoEmpresaProduto;
	private EmpresaProdutoFotoDao daoEmpresaProdutoFoto;
	private Result result;
	private HttpServletResponse response;
	private ProdutoDao daoProduto;
	private EmpresaAtividadeDao daoEmpresaAtividade;
	private Empresa empresa;

	public EmpresaProdutoController(Result result,
			EmpresaProdutoDao daoEmpresaProduto,EmpresaProdutoFotoDao daoEmpresaProdutoFoto,
			HttpServletResponse response,ProdutoDao daoProduto,EmpresaAtividadeDao daoEmpresaAtividade
			,HttpSession session) {
		this.result = result;
		this.daoEmpresaProduto = daoEmpresaProduto;
		this.daoEmpresaProdutoFoto = daoEmpresaProdutoFoto;
		this.daoProduto = daoProduto;
		this.daoEmpresaAtividade = daoEmpresaAtividade;
		this.response = response;
                //Esse trecho em específico causa a exception quanto algum método tem foward ou redirect.
		this.empresa = (Empresa) session.getAttribute("usuario");
	}

	
	@Paginated
	@Path("list")
	public void list(boolean ajax) {
		if (ajax) {
			result.use(Results.json()).from(
					daoEmpresaProduto.listAll(empresa, (Integer) result
							.included().get("start"), (Integer) result
							.included().get("resultsPerPage"))).include("produto").include("fotos").serialize();
		} else {
			this.result.include("totalResults", daoEmpresaProduto.count(empresa));
			this.result.include("empresaProdutoList", daoEmpresaProduto.listAll(empresa,
					(Integer) result.included().get("start"), (Integer) result
							.included().get("resultsPerPage")));
			this.result.include("empresa",empresa);
		}
	}
	
	@Path("foto/{empresaProdutoFoto.id}/{width}/{height}")
	public void foto(EmpresaProdutoFoto empresaProdutoFoto, Integer width, Integer height)
			throws IOException, SQLException {
		IOUtils.copy(this.daoEmpresaProdutoFoto.getPhoto(empresaProdutoFoto, width, height),response.getOutputStream());
		result.use(Results.nothing());
	}

	public void validate(EmpresaProduto empresaProduto) {
		VraptorViewUtil.putErrorInView(
				daoEmpresaProduto.validate(empresaProduto), result);
	}
	
	@Path("pendencia")
	public void pendencia() {
		this.result.include("empresa",empresa);
	}

	@Path("form")
	public void form() {
		if(this.daoEmpresaAtividade.hasPendencia(empresa)) {
			this.result.redirectTo(this).pendencia();
		} else {
			this.result.include("empresa",empresa);
			this.result.include("produtoList", daoProduto
					.listAllBySecaoList(this.daoEmpresaAtividade.listAll(empresa,
							null, null)));
		}
	}
	
	@Path("search")
	public void search(String term) {
		result.use(Results.json())
				.from(daoEmpresaProduto.searchByString(empresa, term))
				.include("produto").include("fotos").serialize();
	}

	
	public void delete(String ids) {
		daoEmpresaProduto.deactive(ids);
		result.use(Results.nothing());
	}

	@Path("edit/{empresaProduto.id}")
	public void edit(EmpresaProduto empresaProduto) {
		result.include("empresaProduto", daoEmpresaProduto.load(empresaProduto.getId()));
		result.forwardTo(this).form();
	}

	@Post
	public void saveOrUpdate(EmpresaProduto empresaProduto,List<UploadedFile> fotos) throws IOException {
		List<InputStream> streams = null;
		if(fotos!=null&&fotos.size()>0) {
			streams = new ArrayList<InputStream>();
			for(UploadedFile uploaded : fotos) {
				streams.add(uploaded.getFile());
			}
		}
		daoEmpresaProduto.saveOrUpdate(empresaProduto,streams);
		result.redirectTo(this).list(false);
	}
}


Eu resolvi de um modo menos elegante que é em cada começo de método receber da sessao o objeto , ai funcionou :

//Injeto session no construtor 
private HttpSession session;
construtor(HttpSession session){
       this.session = session;
}


//E em cada começo dos métodos eu chamo 
Empresa empresa = this.session.getAtributte("usuario");

Seria isso um bug , ou realmente não posso popular direto no construtor um objeto de session ??

no gae o VRaptor instancia o controller passando tudo null no construtor, pra conseguir fazer os proxies (que permitem vc fazer os redirects e os forwards bonitinhos)

só fazer um if (session != null) no construtor

Melhor ainda é usar o SessionScoped ao invés de trabalhar Httpcom Session.getAttribute e HttpSession.setAttribute.

Bom a proposta do Lucas funcionou testando o if(session!=null) .

Então só que não consegui fazer rolar nem a pau no GAE utilizando um componente que encapsula HttpSession , ele fica lançando uma exceção de tudo que eu tentava guardar que não tinha serializado mesmo sendo serializado e ficava perdendo a sessão o tempo todo .

Se quiser fazer um teste . Crie um componente sessionScoped no GAE e tente colocar objetos dentro dele…ele fica perdendo a sessao e fica lançando uma exceção de NotSerializable no componente … e usando direto de HttpSession tudo funcionava certinho!!

colocar implements Serializable no componente não resolve?

[quote=Lucas Cavalcanti]colocar implements Serializable no componente não resolve?

[/quote]

Então mesmo implementando a interface Serializable no componente ele passava o problema pra frente ai dava algo em algum componente que não lembro no Jetty que caia no NotSerializable tb …

qual container vc tá usando?

no guice ou spring o Serializable vai funcionar, no pico não

[quote=Lucas Cavalcanti]qual container vc tá usando?

no guice ou spring o Serializable vai funcionar, no pico não[/quote]

Estou usando o spring mesmo !! Mas pelo que me lembro mesmo com o spring acontecia o problema . Se tiver afim faz o teste ai …pega o blank project do gae , cria um componente sessionScoped e coloca uma entidade usuario dentro dele … depois vai no log de ERROR do console do GAE voce vai ver o erro!!

ah tá, tá dando erro pq o Usuário não é serializable…

qdo ele tenta serializar o seu wrapper ele serializa os campos deles tb, ou seja, o Usuario.

Tenta deixar ele como serializable tb

[quote=Lucas Cavalcanti]ah tá, tá dando erro pq o Usuário não é serializable…

qdo ele tenta serializar o seu wrapper ele serializa os campos deles tb, ou seja, o Usuario.

Tenta deixar ele como serializable tb[/quote]

Mesmo implementando Serializable em Usuario por exemplo ai o erro começa a aparecer no componente exemplo : WebSession dai mesmo implementando Serializable no componente de sessão ai começa a dar um erro no componente interno no jetty que tb não é Serializable… ou seja

mesmo implementando

public class Usuario implements Serializable {
     .
     .
}

@SessionScoped
@Component
public class WebSession implements Serializable {
     .
     .
     
}

ele continua lançando a warning num componente interno do jetty…

se vc fizer ao invés de @SessionScoped um session.setAttribute(“webSession”, new WebSession()) e colocar o usuário dentro dele, funciona?

Desse modo num testei ainda , mais ai acho que só iria complicar as coisas , usar a interface session pra colocar um componente que supostamente seria session tb mas sem anotação,
meio confuso de pensar isso…

Vo deixar como está por enquanto mesmo ja que usando session direto não apresenta problemas , so serializando as classes que vão pra sessão ja funciona tudo bonitinho…

você pode criar o WebSession como @RequestScoped, e internamente o get e set usuário usam a session para guardá-lo