LazyInitializationException + Filter + VRaptor 3 [RESOLVIDO]

Eu apliquei a Open session in view em um Filter.

A primeira coisa que é chamada é o filtro, depois é chamado um interceptor que faz controle de acesso, e esse interceptor redireciona para a página solicitada.

Eu verifico a sessão no meio do caminho e ela está aberta, mas mesmo assim está dando lazy Exception.

Alguém sabe o q pode ser?

Filtro:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
			throws IOException, ServletException {
		try {
			HibernateUtil.currentSession();
			HibernateUtil.beginTransaction();
			
			chain.doFilter(servletRequest, servletResponse);
			
			HibernateUtil.commitTransaction();
		}
		catch(JDBCConnectionException e) {
			e.printStackTrace();
		}
		finally {
			HibernateUtil.closeSession();
		}
	}

HibernateUtil:

public static Session currentSession() {
		Session s = (Session) HibernateUtil.session.get();
		if(s == null) {
			s = HibernateUtil.sessionFactory.openSession();
			HibernateUtil.session.set(s);
		}
		return s;
	}

public static void closeSession() {
		Session s = (Session) HibernateUtil.session.get();
		if(s != null) {
			s.close();
		}
		HibernateUtil.session.set(null);
	}

public static void commitTransaction() {
		Session s = (Session) HibernateUtil.session.get();
		Transaction t = (Transaction) HibernateUtil.transaction.get();
		if(s != null && s.isOpen() && t != null && !t.wasCommitted() && !t.wasRolledBack()) {
			t.commit();
		}
		else {
			throw new IllegalStateException("Erro ao comitar transação");
		}
	}
	
	public static void rollbackTransaction() {
		Session s = (Session) HibernateUtil.session.get();
		Transaction t = (Transaction) HibernateUtil.transaction.get();
		if(s != null && s.isOpen() && t != null && !t.wasCommitted() && !t.wasRolledBack()) {
			t.rollback();
		}
		else {
			throw new IllegalStateException("Erro no rollback da transação");
		}
	}

Local da lazy (minha custom tag):

JspWriter out = this.getJspContext().getOut();
		UserVO user = (UserVO) this.getJspContext().getAttribute("user", PageContext.SESSION_SCOPE);
		MenuItemVO parentMenu = (MenuItemVO) this.getJspContext().getAttribute("parentMenu",
				PageContext.PAGE_SCOPE);
		
		if(user != null && user.getUserType() != null) {
			if(this.render.equalsIgnoreCase("mainMenu")) {
				//Aqui parece q ele ja nao consegue recuperar os objetos
                                List<MenuItemVO> menuItems = user.getUserType().getMenuItems();
				out.println("<table>");
				out.println("<tr>");
                                //Aqui é onde ocorre o lazy exception
				for(MenuItemVO menuItem : menuItems) {
					if(menuItem.getParentMenuItem() == null) {
						out.println("<td>");
						if(menuItem.equals(parentMenu)) {
							out.println("<b>" + menuItem.getNmMenuItem() + "</b>");
						}
						else {
							out.println(menuItem.getNmMenuItem());
						}
						out.println("</td>");
					}
					
				}
				out.println("</tr>");
				out.println("</table>");
			}

Eu fiz uns testes, e caso eu de load no userType antes de dar o getMenuItems ele funciona.

Codigo funcionando:

UserTypeBO userTypeBO = new UserTypeBO();
				try {
					userType = userTypeBO.findById(user.getUserType().getId());
				}
				catch(GenericInitializeException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				List<MenuItemVO> menuItems = userType.getMenuItems();
				out.println("<table>");
				out.println("<tr>");
				for(MenuItemVO menuItem : menuItems) {
					if(menuItem.getParentMenuItem() == null) {
						out.println("<td>");
						if(menuItem.equals(parentMenu)) {
							out.println("<b>" + menuItem.getNmMenuItem() + "</b>");
						}
						else {
							out.println(menuItem.getNmMenuItem());
						}
						out.println("</td>");
					}
					
				}
				out.println("</tr>");
				out.println("</table>");

Como posso resolver isso sem precisar dar o load do objeto do banco manualmente?

O objeto User que contem o UserType está na session.

isso tá acontecendo numa requisição direta, ou através de um redirecionamento?

Lucas, eu acho que entendi o que está acontecendo.

1- O Filtro do hibernate (Open session in view) é chamado.
2- O usuário faz o login, o objeto do usuário é salvo na sessão.
3- O Filtro do hibernate fecha a sessão do hibernate, quando ele fecha está sessão, a sessão hibernate do objeto usuário que está na sessão é fechada também, desta maneira quando eu recupero o objeto usuário ele está sem sessão.

Caso eu faça um load do objeto usuário antes de utilizado tudo ocorre ok.

A minha pergunta é, eu tenho mesmo que dar load no objeto usuário toda vez que pego ele da sessão ou há outra maneira de fazer isso sem precisar ficar dando load?

abraços

vc pode carregar todos os relacionamentos q forem ser usados no usuário na hora que vc colocá-lo na sessão… aí vc dá um session.evict nele, pra tirá-lo da sessão do hibernate…

Como eu faria para carregar todos os relacionamentos?

Teria que carregar usuários, depois load no userType?

Estou achando que para está situação é melhor fazer um relacionamento eager…

vc pode:

  • criar um interceptor que carrega o usuário da sessão a toda requisição…
  • colocar eager nos relacionamentos
  • chamar os getters do seus relacionamentos pra carregá-los assim que colocar o usuário na sessão…

[quote=Lucas Cavalcanti]vc pode:

  • criar um interceptor que carrega o usuário da sessão a toda requisição…
  • colocar eager nos relacionamentos
  • chamar os getters do seus relacionamentos pra carregá-los assim que colocar o usuário na sessão…[/quote]

Como seram poucos dados vou mudar para eager.

Obrigado pela ajuda.

Como seria feito isto? E isto não sobrecarregaria a aplicação fazendo ficar mais lenta?
Ou seria melhor criar dentro do metodo get uma criteria que carrega-se todos os dados?