I can't figure out why, but the Hibernate session is closing before it should, so I can't fetch lazily loaded lists.
In the logs, it's showing that the session closes immediately after hibernateTemplate.findByNamedParam() inside the DAO.
When I run my web app, I get the following error:
Mar 29, 2011 3:13:21 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Spring MVC Dispatcher Servlet] in context with path [/apps] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.communitydriven.apps.entities.Project.tags, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.communitydriven.apps.entities.Project.tags, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272)
at com.communitydriven.apps.managers.ProjectManager.getProject(ProjectManager.java:98)
at com.communitydriven.apps.controllers.ProjectController.getViewProject(ProjectController.java:86)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
My DAO:
@Repository
public class ProjectDao implements IProjectDao {
private HibernateTemplate hibernateTemplate;
@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
...
/**
* {@inheritDoc}
*/
@Override
public Project getProject(Project project) {
// Validate required parameters
if ( (project.getId() == null) ) {
throw new NullPointerException("Missing required parameter: " +
project.toString());
}
// Parameters
List<String> paramNames = new ArrayList<String>();
List<Object> values = new ArrayList<Object>();
// Construct HQL
StringBuffer hql = new StringBuffer();
hql.append("from Project p ");
boolean whereUsed = false; // track of "where" clause has been used
// Filter by Id
if (project.getId() != null) {
whereUsed = DaoUtils.appendFilter(whereUsed, hql);
hql.append("p.id = :id ");
paramNames.add("id");
values.add(project.getId());
}
// Get list of matching projects
@SuppressWarnings("unchecked")
List<Project> projects =
hibernateTemplate.findByNamedParam(
hql.toString(),
paramNames.toArray(new String[paramNames.size()]),
values.toArray());
// Get unique result
Project projectResult = DataAccessUtils.uniqueResult(projects);
return projectResult;
}
}
My Manager:
@Component
public class ProjectManager implements IProjectManager {
@Autowired
private IProjectDao projectDao;
...
/**
* {@inheritDoc}
*/
@Transactional
@Override
public ProjectMO getProject(Long projectId) {
Project project = new Project();
project.setId(projectId);
project = projectDao.getProject(project);
ProjectMO projectMO = new ProjectMO();
projectMO.setId(project.getId());
projectMO.setName(project.getName());
projectMO.setDescription(project.getDescription());
StringBuffer tags = new StringBuffer();
final String DELIMITER = ", ";
for (Tag tag : project.getTags()) {
tags.append(tag.getName() + DELIMITER);
}
projectMO.setTags(tags.toString());
return projectMO;
}
}
The Entity:
@Entity
@Table
public class Project {
private Long id;
private String name;
private String description;
private User submittedBy;
private List<Tag> tags;
public String toString() {
final String DELIMITER = ", ";
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName() + ": [");
sb.append("id: " + id).append(DELIMITER);
sb.append("name: " + name).append(DELIMITER);
sb.append("description: " + description).append("]");
return sb.toString();
}
// GETTERS AND SETTERS //
@Id
@Column
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@OneToOne
@JoinColumn
public User getSubmittedBy() {
return submittedBy;
}
public void setSubmittedBy(User submittedBy) {
this.submittedBy = submittedBy;
}
@ManyToMany
@JoinTable(name="Projects_Tags",
joinColumns={@JoinColumn(name="project_id")},
inverseJoinColumns={@JoinColumn(name="tag_id")})
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
}
My Database context:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=update
</value>
</property>
<property name="packagesToScan" value="com.communitydriven.apps.entities" />
</bean>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>
</beans>
@Transactional helps you to extend scope of Session . Session is open first time when getCurrentSession() is executed and it is closed when transaction ends and it is flushed before transaction commits.
Hibernate SessionFactory openSession() method always opens a new session. We should close this session object once we are done with all the database operations.
When you don't close your Hibernate sessions and therefore do not release JDBC connections, you have what is typically called Connection leak. So, after a number of requests (depending on the size of your connection pool) the server will not be able to acquire a connection to respond your request.
So when you annotate a method with @Transactional , Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating. And when clients make calls into your object, the calls are intercepted and the behaviors injected via the proxy mechanism.
Have you set up OpenSessionInViewFilter?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With