Spring + Hibernate + Struts2

4 respostas
D

Bom dia pessoal,

Estou com um problema e ja procurei em varios lugares e até agora nao encontrei a solução, tomara que alguem aqui me ajude.

Bom o erro é o seguinte:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: br.com.webnetworkmanager.model.Usuario.grupoCollection, no session or session was closed

Isso ocorre pq estou carregando um usuário e tento dar um getGrupos que é uma lista de grupos que está no bag do hibernate e como ele nao esta mantendo a sessao aberta ocorre este erro.

Separei meus arquivos de configuração do spring em 3 arquivos um para o struts outro para o dwr e outro para o data source e minhas classes de servico e daos.

os arquivos de configuração pertinentes abaixo para vcs olharem e verem se tem algo errado.

applicantioContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/tx 
				http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<!--
		DataSource configurado no servidor de aplicações-->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName" value="java:comp/env/jdbc/webNetworkManager" />
	</bean>

	<!--
		<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property
		name="driverClassName" value="com.mysql.jdbc.Driver" /> <property
		name="url" value="jdbc:mysql://localhost:3306/bd" /> <property
		name="username" value="root" /> <property name="password" value="root"
		/> </bean>
	-->
	<!--
		<bean
		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"
		/> <bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" /> <property
		name="jpaVendorAdapter"> <bean
		class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="database" value="MYSQL" /> <property name="showSql"
		value="true" /> </bean> </property> </bean>
	-->
	<!--
		<bean id="sessionFactory" factory-bean="entityManagerFactory"
		factory-method="getSessionFactory" />
	-->


	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="annotatedClasses">
			<list>
				<value>br.com.webnetworkmanager.model.Componente
				</value>
				<value>br.com.webnetworkmanager.model.Estado
				</value>
				<value>br.com.webnetworkmanager.model.Grupo
				</value>
				<value>br.com.webnetworkmanager.model.Hardware
				</value>
				<value>br.com.webnetworkmanager.model.Itemhardware
				</value>
				<value>br.com.webnetworkmanager.model.Software
				</value>
				<value>br.com.webnetworkmanager.model.Tiposcomponente
				</value>
				<value>br.com.webnetworkmanager.model.Tiposlicensa
				</value>
				<value>br.com.webnetworkmanager.model.Unidademedida
				</value>
				<value>br.com.webnetworkmanager.model.Usuario
				</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">false</prop>
				<prop key="hibernate.use_outer_join">true</prop>
				<prop key="hibernate.current_session_context_class">
					org.springframework.orm.hibernate3.SpringSessionContext</prop>
				<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider
				</prop>
				<prop key="hibernate.cache.use_second_level_cache">false</prop>
				<prop key="hibernate.cache.use_query_cache">false</prop>
				<prop key="hibernate.jdbc.batch_size">15</prop>
				<prop key="hibernate.jdbc.use_streams_for_binary">true</prop>
				<!-- prop key="hibernate.default_schema">Prova</prop> -->
				<!-- <prop key="hibernate.hbm2ddl.auto">update</prop> --> 
			</props>

		</property>
	</bean>

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

	<tx:annotation-driven transaction-manager="transactionManager" />

	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<bean id="usuarioDao" class="br.com.webnetworkmanager.dao.UsuarioDao">
		<property name="hibernateTemplate" ref="hibernateTemplate" />
	</bean>
	<bean id="usuarioService" class="br.com.webnetworkmanager.service.UsuarioServiceImpl">
		<constructor-arg ref="usuarioDao" />
	</bean>
	<bean id="estadosDao" class="br.com.webnetworkmanager.dao.EstadosDao">
		<property name="hibernateTemplate" ref="hibernateTemplate" />
	</bean>
	<bean id="estadoService" class="br.com.webnetworkmanager.service.EstadoServiceImpl">
		<constructor-arg ref="estadosDao" />
	</bean>
	<bean id="grupoDao" class="br.com.webnetworkmanager.dao.GrupoDao">
		<property name="hibernateTemplate" ref="hibernateTemplate" />
	</bean>
	<bean id="grupoService" class="br.com.webnetworkmanager.service.GrupoServiceImpl">
		<constructor-arg ref="grupoDao" />
	</bean>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<display-name>WebNetworkManager</display-name>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext*.xml</param-value>
	</context-param>
	<filter>
		<filter-name>hibernateFilter</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
		<init-param>
			<param-name>sessionFactoryBeanName</param-name>
			<param-value>sessionFactory</param-value>
		</init-param>
		<init-param>
			<param-name>singleSession</param-name>
			<param-value>false</param-value>
		</init-param>
		<init-param>
			<param-name>flushMode</param-name>
			<param-value>AUTO</param-value>
		</init-param>

	</filter>
	<filter>
		<filter-name>struts-cleanup</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
	</filter>
	<filter>
		<filter-name>sitemesh</filter-name>
		<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
	</filter>
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
	</filter>

	<filter>
		<filter-name>requestContextFilter</filter-name>
		<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>requestContextFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>struts-cleanup</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>sitemesh</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>hibernateFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<listener>
		<listener-class>
			org.springframework.web.context.request.RequestContextListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<listener>
		<listener-class>net.sf.navigator.menu.MenuContextListener</listener-class>
	</listener>
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>dwr</servlet-name>
		<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
		<init-param>
			<param-name>debug</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>crossDomainSessionSecurity</param-name>
			<param-value>false</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>dwr</servlet-name>
		<url-pattern>/dwr/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
	<resource-ref>
		<description>DB Connection</description>
		<res-ref-name>jdbc/webNetworkManager</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>

	<security-constraint>
		<display-name>webNetworkSecurity</display-name>
		<web-resource-collection>
			<web-resource-name>AllPages</web-resource-name>
			<url-pattern>/jsp/site/*</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>Usuarios</role-name>
			<role-name>Administradores</role-name>
		</auth-constraint>
	</security-constraint>
	<login-config>
		<auth-method>FORM</auth-method>
		<realm-name>webNetworkRealm</realm-name>
		<form-login-config>
			<form-login-page>/jsp/offLogin/loginRedirect.jsp</form-login-page>
			<form-error-page>/jsp/offLogin/loginRedirectError.jsp</form-error-page>
		</form-login-config>
	</login-config>
	<security-role>
		<description>Usuarios com privilegios administradores</description>
		<role-name>Administradores</role-name>
	</security-role>
	<security-role>
		<description>Usuarios do sistema</description>
		<role-name>Usuarios</role-name>
	</security-role>
	<security-role>
		<description>Usuários que não tem mais acesso ao sistema</description>
		<role-name>Inativos</role-name>
	</security-role>

</web-app>

abstraticSpringDao

package br.com.webnetworkmanager.dao;

import java.util.List;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class AbstractSpringDao<T> extends HibernateDaoSupport {

	public AbstractSpringDao() {
	}

	protected void saveOrUpdate(Object obj) {
		getHibernateTemplate().saveOrUpdate(obj);
	}

	protected void delete(Object obj) {
		getHibernateTemplate().delete(obj);
	}

	protected Object find(Class<T> clazz, Integer id) {
		return getHibernateTemplate().get(clazz, id);
	}

	@SuppressWarnings("unchecked")
	protected List<T> findAll(Class<T> clazz) {
		return getHibernateTemplate().find("from " + clazz.getName());
	}

}

UsuarioDao

package br.com.webnetworkmanager.dao;

import java.util.List;

import br.com.webnetworkmanager.model.Usuario;

public class UsuarioDao extends AbstractSpringDao<Usuario> {

	public void delete(Usuario usuario) {
		super.delete(usuario);
	}

	public Usuario find(Integer id) {
		return (Usuario) super.find(Usuario.class, id);
	}

	public List<Usuario> findAll() {
		return super.findAll(Usuario.class);
	}

	public void saveOrUpdate(Usuario usuario) {
		super.saveOrUpdate(usuario);
	}

}

usuarioService

package br.com.webnetworkmanager.service;

import java.util.List;

import br.com.webnetworkmanager.dao.UsuarioDao;
import br.com.webnetworkmanager.model.Usuario;

public class UsuarioServiceImpl implements UsuarioService {
	UsuarioDao usuarioDao;

	public UsuarioServiceImpl(UsuarioDao usuarioDao) {
		this.usuarioDao = usuarioDao;
	}

	@Override
	public List<Usuario> findAll() {
		// TODO Auto-generated method stub
		return usuarioDao.findAll();
	}

	@Override
	public boolean save(Usuario usuario) {
		try {
			usuarioDao.saveOrUpdate(usuario);
			return true;
		} catch (Exception e) {
			// TODO:substituir por logger
			e.printStackTrace();
			return false;
		}

	}

	@Override
	public boolean delete(Integer codUsuario) {
		Usuario user = find(codUsuario);
		if (user != null) {
			usuarioDao.delete(user);
			return true;
		} else {
			return false;
		}
	}

	@Override
	public Usuario find(Integer codUsuario) {

		return usuarioDao.find(codUsuario);
	}

	public UsuarioDao getUsuarioDao() {
		return usuarioDao;
	}

	public void setUsuarioDao(UsuarioDao usuarioDao) {
		this.usuarioDao = usuarioDao;
	}
}

4 Respostas

J

Olá

Eu vejo duas saídas:

1 Pegar tudo que você precisa enquanto sessão está aberta;

2 Na nova sessão informar ao hibernate o objeto novamente.

Veja este post: http://blog.caelum.com.br/2006/11/01/transientobjectexception-lazyinitializationexception-e-outras-famosas-do-hibernate/

D

Acho que o spring gerencia a transação para mim, so queria saber como fazer isso. Fazer com que ele deixe a sessão aberta enquanto estou naquela transação.
Se alguem souber eu agredeço.

J

Olá

Desculpe, pensei que seu problema era o lazy entre sessões, para manter a sessão aberta no visão, coloque este interceptor no seu dispatcher.

<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/index.htm">indexController</prop>
			</props>
		</property>
   		<property name="interceptors">
			<list>
				<bean class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
					<property name="sessionFactory" ref="sessionFactory"/>
				</bean>
            </list>
		</property>
	</bean>
D

Pessoal problema resolvido,

Os filtros do spring devem vir antes dos filtros do struts no tomcat no caso. E tambem eu tinha passado o nome do sesscionFactory incorreto para o parametro init do filtro no web.xml. Não precisei utilizar o interceptor. O OpenSessionInView está mantendo a sessão aberta para mim.

abraços

Criado 21 de janeiro de 2009
Ultima resposta 26 de jan. de 2009
Respostas 4
Participantes 2