Hibernate LazyInitializationException in web application Struts asMVC, Spring as IOC and Hibernate a

A

Amit Jain

I am attempting to create a web application using Struts MVC, Spring
IOC and with Hibernate as its ORM layer.

Exception raised when I try to get memberVO object. Problem with
Hibernate Lazy initialization.

stack trace:
-------------------------------------------------------------
javax.servlet.ServletException:
org.hibernate.LazyInitializationException: failed to lazily initialize
a collection of role: com.yashbinary.crtracker.vo.MemberVO.apsses, no
session or session was closed
org.apache.struts.action.RequestProcessor.processException
(RequestProcessor.java:535)
org.apache.struts.action.RequestProcessor.processActionPerform
(RequestProcessor.java:433)

com.yashbinary.crtracker.struts.controller.XRequestProcessor.processActionPerform
(XRequestProcessor.java:45)
org.apache.struts.action.RequestProcessor.process
(RequestProcessor.java:236)
com.yashbinary.crtracker.struts.controller.XRequestProcessor.process
(XRequestProcessor.java:32)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:
1196)
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter
(MonitorFilter.java:390)

org.hibernate.LazyInitializationException: failed to lazily initialize
a collection of role: com.yashbinary.crtracker.vo.MemberVO.apsses, no
session or session was closed
at
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException
(AbstractPersistentCollection.java:358)
at
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected
(AbstractPersistentCollection.java:350)
at
org.hibernate.collection.AbstractPersistentCollection.initialize
(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read
(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.hashCode
(PersistentSet.java:411)
at java.util.HashMap.containsKey(HashMap.java:377)
at java.util.HashSet.contains(HashSet.java:182)
at
org.apache.commons.lang.builder.ReflectionToStringBuilder.isRegistered
(ReflectionToStringBuilder.java:133)
at
org.apache.commons.lang.builder.ReflectionToStringBuilder.appendFieldsIn
(ReflectionToStringBuilder.java:629)
at
org.apache.commons.lang.builder.ReflectionToStringBuilder.toString
(ReflectionToStringBuilder.java:789)
at
org.apache.commons.lang.builder.ReflectionToStringBuilder.toString
(ReflectionToStringBuilder.java:355)
at
org.apache.commons.lang.builder.ReflectionToStringBuilder.toString
(ReflectionToStringBuilder.java:173)
at com.yashbinary.crtracker.common.ValueObject.toString
(ValueObject.java:23)
at java.lang.String.valueOf(String.java:2615)
at java.lang.StringBuilder.append(StringBuilder.java:116)
at com.yashbinary.crtracker.struts.login.LoginAction.execute
(LoginAction.java:52)
at org.springframework.web.struts.DelegatingActionProxy.execute
(DelegatingActionProxy.java:106)
at
org.apache.struts.action.RequestProcessor.processActionPerform
(RequestProcessor.java:431)
at
com.yashbinary.crtracker.struts.controller.XRequestProcessor.processActionPerform
(XRequestProcessor.java:45)
at org.apache.struts.action.RequestProcessor.process
(RequestProcessor.java:236)
at
com.yashbinary.crtracker.struts.controller.XRequestProcessor.process
(XRequestProcessor.java:32)
at org.apache.struts.action.ActionServlet.process
(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doPost
(ActionServlet.java:432)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:
637)
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
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter
(MonitorFilter.java:390)
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:286)
at org.apache.coyote.http11.Http11Processor.process
(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol
$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run
(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
-----------------------------------------------------------------------------------

Here is a code:
---------------------------------------

hibernate.cfg.xml
---------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate
Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-
configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property
name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</
property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:
3306/crtracker</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<mapping resource="com/yashbinary/crtracker/vo/h_mapping/
Apss.hbm.xml"/>
<mapping resource="com/yashbinary/crtracker/vo/h_mapping/
Member.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Member.hbm.xml
--------------------------------
<hibernate-mapping>
<class name="com.yashbinary.crtracker.vo.MemberVO" table="member"
catalog="crtracker">
<id name="empId" type="int">
<column name="emp_id" />
<generator class="assigned" />
</id>
<property name="firstName" type="string">
<column name="first_name" length="50" />
</property>
<property name="lastName" type="string">
<column name="last_name" length="50" />
</property>
<property name="emailId" type="string">
<column name="email_id" length="20" />
</property>
<property name="password" type="string">
<column name="password" length="10" />
</property>
<set name="apsses" inverse="true">
<key>
<column name="owner" not-null="true" unique="true" />
</key>
<one-to-many class="com.yashbinary.crtracker.vo.ApssVO" />
</set>
</class>
</hibernate-mapping>

applicationContext.xml
-------------------------------------------------
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<list> <value>com/yashbinary/crtracker/vo/h_mapping/
Member.hbm.xml</value>
<value>com/yashbinary/crtracker/vo/h_mapping/
Apss.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>

MemberVO.java
-----------------------------------------
package com.yashbinary.crtracker.vo;
import com.yashbinary.crtracker.common.ValueObject;
import java.util.HashSet;
import java.util.Set;
public class MemberVO extends ValueObject implements
java.io.Serializable {
private int empId;
private String firstName;
private String lastName;
private String emailId;
private String password;
private Set<ApssVO> apsses = new HashSet<ApssVO>(0);
public MemberVO() {
}
public MemberVO(int empId) {
this.empId = empId;
}
public MemberVO(int empId, String firstName, String lastName, String
emailId, String password, Set<ApssVO> apsses) {
this.empId = empId;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
this.password = password;
this.apsses = apsses;
}

// setter n getter for empId, firstName, lastName, emailId,
password

public Set<ApssVO> getApsses() {
return this.apsses;
}
public void setApsses(Set<ApssVO> apsses) {
this.apsses = apsses;
}
}

MemberDAO.java
----------------------------------
package com.yashbinary.crtracker.member.dao;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class MemberDAO extends HibernateDaoSupport implements
DataAccessObject {

public ValueObject findByCriteria(MemberVO memberVO) throws
DataAccessException{
log.debug("findByCriteria() start");
Session session = null;
Criteria criteria = null;
MemberVO returnVO = null;
try{
session = getHibernateTemplate().getSessionFactory
().openSession();
criteria = session.createCriteria(MemberVO.class);

criteria.add(Restrictions.eq("empId", memberVO.getEmpId
() ) );
criteria.add(Restrictions.eq("password",
memberVO.getPassword() ) );

//returnVO = (MemberVO) criteria.uniqueResult();
List returnVOList = criteria.list();
if(returnVOList!=null){
returnVO = (MemberVO)returnVOList.get(0);
}
}catch(HibernateException e){
log.error("HibernateException thrown in
MemberDAO.findByCriteria()", e);
}catch(ServiceLocatorException e){
log.error("ServiceLocatorException thrown in
MemberDAO.findByCriteria()", e);
}finally{
if(session!=null)
session.close();
}
log.debug("findByCriteria() end");
return returnVO;
}
}

MemberManagerBD.java
-----------------------------------------------
public class MemberManagerBD {
public MemberVO authenticate(String empId, String password) throws
ApplicationException{
MemberDAO memberDAO = getMemberDAO();
MemberVO memberVO = (MemberVO) memberDAO.findByCriteria
(memberVO);
return memberVO;
}

LoginAction.java
---------------------------------------
public class LoginAction extends org.apache.struts.action.Action {
public ActionForward execute(){
MemberManagerBD memManagerBD = getMemberMangerBD();
memberVO = memManagerBD.authenticate(((LoginForm)form).getEmpId(),
((LoginForm)form).getPassword()
);
}
}

Thanks in advance for your help

Amit Jain
 
A

Amit Jain

try OpenSessionInViewFilter supplied by Springframework.

Thanks for you reply,

I checked expection and found that it cause because of overridden
toString() method of class abstact ValuObject.java

public abstract class ValueObject {

/** Creates a new instance of ValueObject */
public ValueObject() {
}

public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
ValueObject's toString() method is the cause of exception. But I don't
understand why this toString method through exception.
I have taken reference of example mentioned in book pro-apache-struts
with ajax by Apress.

Once again thanks alot for your reply...

Amit Jain
 
J

Jean-Baptiste Nizet

Amit Jain a écrit :
Thanks for you reply,

I checked expection and found that it cause because of overridden
toString() method of class abstact ValuObject.java

public abstract class ValueObject {

/** Creates a new instance of ValueObject */
public ValueObject() {
}

public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}
ValueObject's toString() method is the cause of exception. But I don't
understand why this toString method through exception.

You need to understand how Hibernate handles XXX-to-many lazy
relationships. Hibernate doesn't load all the objects of the collection
directly. Instead, when you invoke a method of the collection for the
first time, it executes an additional database query to load all the
objects of the collection. In order for this query to work, the object
must be associated to an open session. I suspect that you're doing the
following:
1. open a session
2. load your value object using the session
3. close the session
4. call the toString() method on the value object

Since your toString() method probably invokes all the getters it finds
on the value object and certainly invoke toString() on the result,
Hibernate tries to load the objects in the collection, but your session
is closed. So you have two solutions:

1. make sure you don't access non-loaded objects or collections of
detached objects
2. make sure the session stays open until you're done with the object,
in other words, don't use detached objects.

Anyway, such an implementation of toString() will cause problems with
detached hibernate objects.

JB.
 
L

Lew

Jean-Baptiste Nizet said:
You need to understand how Hibernate handles XXX-to-many lazy
relationships. Hibernate doesn't load all the objects of the collection
directly. Instead, when you invoke a method of the collection for the
first time, it executes an additional database query to load all the
objects of the collection. In order for this query to work, the object
must be associated to an open session. I suspect that you're doing the
following:
1. open a session
2. load your value object using the session
3. close the session
4. call the toString() method on the value object

Since your toString() method probably invokes all the getters it finds
on the value object and certainly invoke toString() on the result,
Hibernate tries to load the objects in the collection, but your session
is closed. So you have two solutions:

1. make sure you don't access non-loaded objects or collections of
detached objects
2. make sure the session stays open until you're done with the object,
in other words, don't use detached objects.

Anyway, such an implementation of toString() will cause problems with
detached hibernate objects.

Even absent the lazy-load behavior (also fixable by eager loading, BTW), that
may not be the most desirable implementation of 'toString()'. Does a list of
all the associated objects really belong in the 'toString()' representation?
What if they have a many-to-one relationship back to the parent object and
their 'toString()' tries to list it? You'd have a cycle that you can't break.
 
A

Amit Jain

Thanks to All for there valuable inputs.

Things are very clear from analysis. I remove the method toString()
from ValueObject abstract class. And Hibernate exeption related to
Lazy initialization is removed.

But I don't know what will be the impact on the flow by removal of
toString() method.

Thanks & Regards,
Amit Jain
 
L

Lew

Amit said:
But I don't know what will be the impact on the flow by removal of
toString() method.

What was its purpose in the flow?

How did you implement it in the abstract class?

Bear in mind that you didn't remove the 'toString()' method, only the specific
implementation.

Could you implement it differently?

What do you want it to do for you?
 
A

Amit Jain

The Value Objects are used in the application: MemberVO, apssVO. All
of these classes extend an abstract class called ValueObject. (The
Value Object pattern can be implemented in a number of ways.) The code
for the ValueObject class is shown here:
package com.yashbinary.crtracker.common;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
public abstract class ValueObject {
/** Creates a new instance of ValueObject */
public ValueObject() {
}
public String toString() {
return ReflectionToStringBuilder.toString(this);
}
}

The ValueObject class serves as a good base class for putting methods
that are going to be
shared across all Value Objects in the application. we needed to dump
the contents of a JavaBean. Rather than writing own method to do this,
we used the ReflectionToStringBuilder class from the Jakarta Commons
lang project. The Commons lang project provides several “helper”
utilities for carrying out most low-level tasks related to the core
java.lang classes. The ReflectionToStringBuilder classes use Java
reflection to build a string containing all of the properties within a
class. By overriding the toString() method on the base ValueObjects
and using the
ReflectionToStringBuilder class, in three lines of code we were able
to have a consistent
mechanism for dumping the contents of a JavaBean. The preceding
example only shows a
very simple use of the ReflectionToStringBuilder class.
In the application, the ValueObject interface is used as a marker
interface to
indicate that the class is a Value Object. This interface has no
method signatures and provides
a generic type for passing data in and out of a DAO. By passing only
ValueObjects in the
DataAccessObject interface, you can guarantee that every DAO in the
application
supports a base set of CRUD functionality. It is the responsibility of
the DAO to cast the
ValueObject to the type it is expecting.

I am taking reference from book "pro-apache-struts-with-ajax"
publisher Apress.

Thanks & Regards,
Amit Jain
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top