Hello Forum,
making my first steps with hibernate I started developing a little knowledge
base application using Java, Swing and of course hibernate. The application has four tables: Users, Categories, Entries and Attachments. The categories and the entries held by the categories are visualized using a subclass of JTree and a subclass of DefaultMutableTreeNode. To prevent users from working on old data that might has been changed by another user I set up a TimerTask and associated an ActionListener on it that shall update the currently expanded node at given intervals. While implementing the code for the ActionPerformed method I encountered the following problem:
I start two instances of the application, select a node in both program instances and change the node in the first instance. The node in the second instance becomes updated
and everything works as expected - for about 20 minutes (the more instances I start the shorter the time to the error). After some time I get an exception (see fullstack trace below) that says:
java.lang.NoSuchMethodError: de.edvbm.jkb.util.data.pojos.User.getHibernateLazyInitializer()Lorg/hibernate/proxy/LazyInitializer;
1. I don't understand why the exception is thrown referencing a method from the User class.
The only things I compare within the equals method of class Entry is the entryTtitle and the entryText.
Yes, I have a many-to-one mapping in the Entry class that references a User object but I don't use it to compare the two entities.
2. Why is the code running for about 15 - 20 minutes with 5-6 instances of my application without any exception?
The sessions I use are always fresh ones retunred from the session factory.
Hibernate version:
3.1.1
Mapping documents:
Hibernate config file:
Code:
<?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>
<!-- Define Db connection settings -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="hibernate.connection.username">mainDBUser</property>
<property name="hibernate.connection.password">xxxxxxxx</property>
<property name="hibernate.connection.url">jdbc:mysql://jupiter.edvbm.local/jkb</property>
<!-- c3p0 connection Pool settings -->
<property name="hibernate.c3p0.min_size">4</property>
<property name="hibernate.c3p0.max_size">50</property>
<property name="hibernate.c3p0.acquire_increment">2</property>
<property name="hibernate.c3p0.validate">true</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">false</property>
<!-- Define mappings -->
<mapping resource="de/edvbm/jkb/util/data/pojos/Attachment.hbm.xml"/>
<mapping resource="de/edvbm/jkb/util/data/pojos/Category.hbm.xml"/>
<mapping resource="de/edvbm/jkb/util/data/pojos/Entry.hbm.xml"/>
<mapping resource="de/edvbm/jkb/util/data/pojos/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Mapping file of the Entry class
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="de.edvbm.jkb.util.data.pojos">
<class name="Entry" table="entry">
<id column="entry_Id" name="entryId" type="long">
<generator class="native"/>
</id>
<many-to-one name="owner" column="entry_created_by_user_Id" class="User" unique="true" not-null="true"/>
<many-to-one name="category" column="entry_category_id" class="Category" unique="true" not-null="true"/>
<property name="entryTitle" column="entry_title" length="255" type="string" not-null="true"/>
<property name="entryText" column="entry_text" length="2147483647" type="string"/>
<property name="entryCreationDate" column="entry_creation_date" type="java.util.Date" not-null="true"/>
</class>
</hibernate-mapping>
Mapping file of the User class:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="de.edvbm.jkb.util.data.pojos">
<class name="User" table="user">
<id column="user_Id" name="userId" type="long">
<generator class="native"/>
</id>
<property name="userFirstName" column="user_first_Name" type="string" length="100" not-null="true"/>
<property name="userLastName" column="user_last_Name" type="string" length="100" not-null="true"/>
<property name="userLoginName" column="user_login_Name" type="string" length="100" not-null="true"/>
<property name="userPassword" column="user_password" type="string" length="100" not-null="true"/>
<property name="userStatus" column="user_status" type="string" length="100" not-null="true"/>
<property name="userCreationDate" column="user_creation_date" type="java.util.Date" not-null="true"/>
</class>
</hibernate-mapping>
The ActionPerformed method that is used by the TimerTask that looks for node changes at given intervals:
Code:
public void actionPerformed(final ActionEvent e) {;
currSelectedTreePath = tree.getSelectionPath();
if (currSelectedTreePath != null) {
JkbTreeNode currTreeNode = (JkbTreeNode) currSelectedTreePath.getLastPathComponent();
if (currTreeNode.isPopulatedWithData()) {
refreshCurrentTreeNode(currTreeNode);
}
} // End if - Main check for tree path unequal to null
} // End of ActionPerformed()
/*---------------------------------------------------------------------------*/
private void refreshCurrentTreeNode(final JkbTreeNode currTreeNode) {
Object currUserObject;
if (currTreeNode.getChildCount() > 0) {
Enumeration childList = currTreeNode.children();
while (childList.hasMoreElements()) {
JkbTreeNode currChild = (JkbTreeNode) childList.nextElement();
currUserObject = currChild.getUserObject();
if (currUserObject instanceof Category
&& currChild.isPopulatedWithData()
&& tree.isExpanded(currSelectedTreePath)) {
refreshCurrentTreeNode(currChild);
}
else {
if (currUserObject instanceof Entry) {
// Here comes the comparison of the object from the node and the object loaded from the database:
Session session = context.getSessionFactory().openSession();
Entry entryFromNode = null;
Entry entryFromDb = null;
entryFromNode = (Entry) currUserObject;
entryFromDb = (Entry) session.load(Entry.class, entryFromNode.getEntryId());
if (entryFromNode != null && entryFromDb != null) {
if (!entryFromNode.equals(entryFromDb)) {
DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
currChild.setUserObject(entryFromDb);
treeModel.reload(currChild);
}
}
session.close();
// End of session related stuff
} // End if - Instance is of type Entry
} // End else case
} // End while loop
} // End if - Check for child list size greater 0
else { // A leaf is selected - so check all Entrys in the category
refreshCurrentTreeNode((JkbTreeNode) currTreeNode.getParent());
}
} // End of refreshCurrentTreeNode()
I think the problem occurs when comparing the two objects, the equals method of the Entry class::
Code:
/*---------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(final Object other) {
if (!(other instanceof Entry)) {
return false;
}
if (this == other) {
return true;
}
Entry rhs = (Entry) other;
return new EqualsBuilder().appendSuper(super.equals(rhs))
.append(this.getEntryTitle(), rhs.getEntryTitle())
.append(this.getEntryText(), rhs.getEntryText())
.isEquals();
} // End of equals
Full stack trace of any exception that occurs:Code:
Exception in thread "AWT-EventQueue-0" java.lang.NoSuchMethodError: de.edvbm.jkb.util.data.pojos.User.getHibernateLazyInitializer()Lorg/hibernate/proxy/LazyInitializer;
at de.edvbm.jkb.util.data.pojos.User$$EnhancerByCGLIB$$81ad8901.getHibernateLazyInitializer(<generated>)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:274)
at org.hibernate.type.EntityType.resolve(EntityType.java:303)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:113)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:93)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:81)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:82)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:889)
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:847)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:62)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:158)
at de.edvbm.jkb.util.data.pojos.Entry$$EnhancerByCGLIB$$7f354dce.getEntryTitle(<generated>)
at de.edvbm.jkb.util.data.pojos.Entry.equals(Entry.java:143)
at de.edvbm.jkb.util.data.pojos.Entry$$FastClassByCGLIB$$73b8d235.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:161)
at de.edvbm.jkb.util.data.pojos.Entry$$EnhancerByCGLIB$$7f354dce.equals(<generated>)
at de.edvbm.jkb.util.listener.action.mainApp.timer.RefreshSelectedTreePathAction.refreshCurrentTreeNode(RefreshSelectedTreePathAction.java:178)
at de.edvbm.jkb.util.listener.action.mainApp.timer.RefreshSelectedTreePathAction.refreshCurrentTreeNode(RefreshSelectedTreePathAction.java:197)
at de.edvbm.jkb.util.listener.action.mainApp.timer.RefreshSelectedTreePathAction.actionPerformed(RefreshSelectedTreePathAction.java:110)
at javax.swing.Timer.fireActionPerformed(Timer.java:271)
at javax.swing.Timer$DoPostEvent.run(Timer.java:201)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
Name and version of the database you are using:
MySQL, 5.0.15-nt-max
Any help would be greatly appreciated.
Have a nice Weekend!
Henning Malzahn