Hi,
I understand that this exception is quite self-explanatory:
Code:
net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
However, I can't identify where in my code it could possibly be. I am using the struts plug-in. I have a form, an action to initialize the form, and the action that is performed when the form is submitted. It is in the submission action, when I try to update one of my collections, that I get this error (and strangely, not the other collection which is initialized in much the same way). I have several object managers that contain a session object. The constructor of these managers grab a session from the sessionFactory. In the finalize method, these managers close the session, so that they do not persist over one request.
Please tell me where the two open sessions/collections are! I will try to include everything but let me know if you need more information.
Here is the structure Study contains a Collection of Versions that has a collection of versionStatuses. As you will see in the log output, versionStatus updates just fine:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<!-- table created by: CREATE TABLE KEYWORDS ( ID IDENTITY, NAME VARCHAR(25) ); -->
<class name="com.cc.tss.Study" table="study">
<id name="id" type="integer" column="id">
<generator class="sequence">
<param name="sequence">study_id_seq</param>
</generator>
</id>
<property name="number" column="num" type="int" not-null="true"/>
<property name="description" column="name" type="string"/>
<property name="inUse" column="in_use" type="boolean"/>
<property name="dueDate" column="due_date" type="date"/>
<set
name="versions"
inverse="true"
lazy="true"
order-by="name asc">
<key column="study_id"/>
<one-to-many class="com.cc.tss.Version"/>
</set>
<many-to-one
name="studyType"
class="com.cc.tss.StudyType"
column="type"/>
<many-to-one
name="allocation"
class="com.cc.tss.Allocation"
column="allocation_id"/>
</class>
</hibernate-mapping>
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<!-- table created by: CREATE TABLE KEYWORDS ( ID IDENTITY, NAME VARCHAR(25) ); -->
<class name="com.cc.tss.Version" table="version">
<id name="id" type="integer" column="id">
<generator class="sequence">
<param name="sequence">version_id_seq</param>
</generator>
</id>
<property name="name" column="name" type="string" not-null="true"/>
<property name="numberOfCompletionsRequired" column="comp_req" type="int"/>
<property name="estimatedTiming" column="est_timing" type="float"/>
<property name="inUse" column="in_use" type="boolean"/>
<set
name="versionStatusCode"
inverse="true"
lazy="true">
<key column="version_id"/>
<one-to-many class="com.cc.tss.VersionStatus"/>
</set>
<many-to-one
name="study"
class="com.cc.tss.Study"
column="study_id"/>
</class>
</hibernate-mapping>
Here is my Initialize form action:
Code:
public final class ManageStudyFormInit extends Action {
static Logger log = Logger.getLogger(ManageStudyFormInit.class);
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse response)
throws Exception {
log.debug("initializing managestudy form");
HttpSession session = request.getSession();
if (form == null) {
form = (ActionForm) session.getAttribute(mapping.getAttribute());
if (form == null) {
log.debug("creating new form named " + mapping.getAttribute() +" in " + mapping.getScope());
form = new ManageStudyForm();
if ("request".equals(mapping.getScope()))
request.setAttribute(mapping.getAttribute(), form);
else
session.setAttribute(mapping.getAttribute(), form);
}
}
ManageStudyForm msf = (ManageStudyForm) form;
StudyManager sm = null;
Study study = null;
try {
sm = new StudyManager();
Integer id = null;
String queryString = request.getQueryString();
if (queryString != null) {
Properties p = Util.parseQueryString(queryString);
id = Integer.valueOf(p.getProperty("id"));
}
if (id == null) {
id = (Integer) request.getAttribute("id");
}
if (id != null) {
study = sm.getStudy(id);
} else {
log.debug("Making new study");
study = new Study();
}
} catch (Exception e) {
log.debug("Error initializing timesheetform", e);
}
msf.setStudy(study);
log.debug("got study");
try {
setOptions(msf, study);
} catch (Exception e) {
log.debug("Error setting options", e);
}
log.debug("Setting transactional control token");
saveToken(request);
log.debug("Done init");
sm = null;
return (mapping.findForward("success"));
}
private void setOptions(ManageStudyForm msf, Study study) throws Exception {
log.debug("setOptions()");
Collection versions = study.getVersions();
ArrayList vers = new ArrayList(versions);
msf.setVersions(vers);
ArrayList selectVersions = new ArrayList();
ArrayList versionStatuses = new ArrayList();
if (versions != null) {
Iterator it = versions.iterator();
while (it.hasNext()) {
Version v = (Version) it.next();
log.debug("Version " + v.getId());
selectVersions.add(new SelectItem(v.getId(), v.getName(), v.getName()));
versionStatuses.addAll(v.getVersionStatusCode());
}
}
msf.setSelectVersions(selectVersions);
msf.setVersionStatuses(versionStatuses);
AllocationManager am = new AllocationManager();
StudyTypeManager stm = new StudyTypeManager();
ArrayList allocations = am.getAllocations();
ArrayList studyTypes = stm.getStudyTypes();
ArrayList selectStudyTypes = new ArrayList();
ArrayList selectAllocations = new ArrayList();
if (studyTypes != null) {
Iterator it = studyTypes.iterator();
while (it.hasNext()) {
StudyType v = (StudyType) it.next();
selectStudyTypes.add(new SelectItem(v.getId(), v.getDescription(), v.getDescription()));
}
}
selectAllocations.add(new SelectItem(new Integer(0), "", ""));
if (allocations != null) {
Iterator it = allocations.iterator();
while (it.hasNext()) {
Allocation v = (Allocation) it.next();
selectAllocations.add(new SelectItem(v.getId(), v.getDescription(), v.getDescription()));
}
}
msf.setStudyTypes(selectStudyTypes);
msf.setAllocations(selectAllocations);
PayTypeManager patm = new PayTypeManager();
PieceTypeManager pitm = new PieceTypeManager();
ArrayList payTypes = patm.getPayTypes();
ArrayList pieceTypes = pitm.getPieceTypes();
ArrayList selectPieceTypes = new ArrayList();
ArrayList selectPayTypes = new ArrayList();
if (payTypes != null) {
Iterator it = payTypes.iterator();
while (it.hasNext()) {
PayType v = (PayType) it.next();
selectPayTypes.add(new SelectItem(v.getId(), v.getType(), v.getType()));
}
}
if (pieceTypes != null) {
Iterator it = pieceTypes.iterator();
while (it.hasNext()) {
PieceType v = (PieceType) it.next();
selectPieceTypes.add(new SelectItem(v.getId(), v.getName(), v.getName()));
}
}
msf.setPayTypes(selectPayTypes);
msf.setPieceTypes(selectPieceTypes);
log.debug("done setOptions");
}
}
Here is the post-submission action:
Code:
public final class ManageStudyAction extends Action {
static Logger log = Logger.getLogger(ManageStudyAction.class);
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
try {
log.debug("entryAction execute()");
ActionErrors errors = null;
StudyManager sm = null;
ManageStudyForm f = (ManageStudyForm) form;
Study study = f.getStudy();
VersionStatusCodeManager vscm = null;
study.setVersions(f.getVersions());
ArrayList vses = f.getVersionStatuses();
f = null;
HttpSession session = request.getSession();
session.setAttribute(mapping.getName(), f);
try {
sm = new StudyManager();
} catch (Exception e) {
log.debug("Error initializing managers", e);
}
try {
sm.editStudy(study);
sm = null;
vscm = new VersionStatusCodeManager();
if (!vses.isEmpty()) {
vscm.editVersionStatus(vses);
}
} catch (Exception e) {
log.debug("Error calculating time", e);
}
log.debug("ManageStudyAction complete");
log.debug("going to " + mapping.findForward("success"));
} catch (Exception e) {
log.debug("Error", e);
}
return (mapping.findForward("success"));
}
}
Here is the editStudy function from StudyManager:
Code:
Collection versions = study.getVersions();
try {
session.saveOrUpdate(study);
Iterator it = versions.iterator();
while (it.hasNext()) {
Version v = (Version) it.next();
if (v == null) continue;
log.debug("saveOrUpdate version " + v.getId());
session.saveOrUpdate(v);
}
log.debug("flushing");
session.flush();
} catch (JDBCException et) {
SQLException ext = et.getSQLException();
while (ext != null) {
log.debug("next", ext);
ext = ext.getNextException();
}
} catch (HibernateException he) {
log.debug("Error in updating study: ", he);
} catch (Exception e) {
log.debug("Error in updating study: ", e);
}
log.debug("done update");
return 0;
Here is my log output:
Code:
2004-01-22 22:42:45,436 -- DEBUG com.cc.tss.ManageStudyForm -- ManageStudyform validate()
2004-01-22 22:42:45,437 -- DEBUG com.cc.tss.ManageStudyForm -- validate done
2004-01-22 22:42:45,441 -- DEBUG com.cc.tss.ManageStudyAction -- entryAction execute()
2004-01-22 22:42:45,470 -- DEBUG com.cc.tss.StudyManager -- saveOrUpdate version 2
2004-01-22 22:42:45,477 -- DEBUG com.cc.tss.StudyManager -- Error in updating study:
net.sf.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
...
2004-01-22 22:42:45,497 -- DEBUG com.cc.tss.StudyManager -- done update
2004-01-22 22:42:45,511 -- DEBUG com.cc.tss.VersionStatusCodeManager -- editVersionStatus
2004-01-22 22:42:45,512 -- DEBUG com.cc.tss.VersionStatusCodeManager -- updating 1
2004-01-22 22:42:45,512 -- DEBUG com.cc.tss.VersionStatusCodeManager -- flushing
2004-01-22 22:42:45,576 -- DEBUG com.cc.tss.VersionStatusCodeManager -- done flushing
2004-01-22 22:42:45,576 -- DEBUG com.cc.tss.ManageStudyAction -- ManageStudyAction complete