Question

Edit 5/11/2011:

I guess it's a bit worse than what's below; in my deployed QA instance, if I just refresh the main dashboard a number of times, eventually my user's many-to-many group associations are deleted. At this point, there are only select statements being called on the server side; hopefully I'm getting it narrowed down with these latest tests.

Original:

Hi all. I'm having a problem with a rather complex object; problem is as follows: when I send the object from the client to server to be saved, it is seemingly randomly wiping out many-to-many relationships on associated objects. Worse yet, I am not able to reproduce the problem myself, after roughly two months of being aware of the problem. I have the app out for testing with a QA group; they're using the program daily, double entering in the new and legacy applications. The problem crops up as much as three times a day.

I'll do my best to provide as much detail as I can, and greatly appreciate anyone taking a look!

The app framework is GWT 2.1 + Gilead + Hibernate 3 + MySQL InnoDB. I'm letting Hibernate handle any cascading etc, so none is defined in the DB, although all foreign keys are set in the DB.

Here's some excerpts from the mappings:

<hibernate-mapping>
 <class name="com.example.domain.Close" table="CLOSE">

 <many-to-one name="updateUser"
class="com.example.domain.User"
column="LAST_UPDATE_USER"/>
 </class>
</hibernate-mapping>

<hibernate-mapping>
  <class name="com.example.domain.User" table="USER" batch-size="25">
    <set name="groups" table="USER_GROUP" lazy="true" batch-size="25">
      <key column="USER_ID"/>
      <many-to-many column="GROUP_ID" class="com.example.domain.Group"/>
    </set>
  </class>
</hibernate-mapping>

<hibernate-mapping>
  <class name="com.example.domain.Group" 
    table="GROUP" batch-size="25">
    <set name="users" table="USER_GROUP" lazy="true" inverse="true">
      <key column="GROUP_ID"/>
      <many-to-many column="USER_ID" class="com.example.domain.User"/>
    </set>
    <set name="permissions" table="PERMISSION_GROUP" lazy="true" inverse="true">
    <key column="GROUP_ID"/>
    <many-to-many column="PERMISSION_ID" 
      class="com.example.domain.Permission"/>
    </set>

<hibernate-mapping>
  <class name="com.example.domain.Permission" 
      table="PERMISSION">
    <set name="groups" table="PERMISSION_GROUP" lazy="true">
      <key column="PERMISSION_ID"/>
      <many-to-many column="GROUP_ID" 
        class="com.example.domain.Group"/>
    </set>
  </class>
</hibernate-mapping>

Saving the object is simple a call to saveOrUpdate():

Session session = gileadHibernateUtil.getSessionFactory()
  .getCurrentSession();
session.beginTransaction();
try {
  session.saveOrUpdate(close);
} catch (Exception e) {
  e.printStackTrace();
  session.getTransaction.rollback();
}
session.getTransaction.commit();

return close;

The Close 'updateUser' is an object loaded when the user logs in. It is loaded with the associated groups and permissions so the system can grant/deny access to app modules. I do

close.setUpdateUser(exampleApp.getUser()); 

before sending the object back to the server.

There are plenty of other places in the app where this sort of operation happens, but doesn't cause the unwanted side-effects. It probably boils down to the complexity of the client-side code associated with the Close object, or rather, my implementation of it.

I've spent so much time pouring over the official Hibernate docs, looking for possibly related problems, etc, I thought maybe it was a good time to ask for help. I have to man up and keep at it, but maybe just asking will help me figure it out.

I'm not sure what else to provide right now that's relevant. Hopefully what is here so far has relevance!

Thanks for listening!

Edit

May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: insert into example_dev.RECENT_ITEM (OBJECT_TYPE, OBJECT_ID, DATE, USER_ID) values (?, ?, ?, ?)
May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: delete from example_dev.PERMISSION_GROUP where PERMISSION_ID=?
May  5 12:18:38 localhost last message repeated 19 times
May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: delete from example_dev.USER_GROUP where USER_ID=?
May  5 12:18:38 localhost jsvc.exec[10117]: Hibernate: delete from example_dev.USER_DESIGNATION where USER_ID=?

It appears that deletes are happening right after this insert.. previous operations are all selects. But nothing in User should be cascading from RecentItem.

Was it helpful?

Solution

After a lot of research, I came to some conclusions and was able to take action. First off, I learned after quite a bit of searching on the Gilead forum, that it is no longer being actively maintained. Should have noticed that sooner. Meanwhile, I had started reading about RequestFactory, and after a couple days of research, decided I should try migrating to this.

This is a rather large project, roughly 50 domain objects, some with many object associations. It took me around 40-50 hours to rewrite everything from using Gilead + GWT RPC to using RequestFactory exclusively. I am pretty happy with the resulting changes in code and structure. I'm not too bothered thus far by having to create DTO proxy objects, and I took the opportunity to switch to Hibernate Annotations, getting rid of the mapping files.

It was tricky at times to refactor the code to utilize the fetch/edit/save cycles that RequestFactory requires. It did give me the opportunity to improve upon some of the code.

The good news is, the problem has been resolved. No more many-to-many associations being mysteriously deleted. My best guess is I was hitting a bug in Gilead, or my usage of it was incorrect, or it is possible I resolved a problem when migrating to Annotations.

I ran across some great resources while learning RequestFactory+Hibernate, many through StackOverflow (thanks again!):

Using GWT RequestFactory with Objectify - was great to get a feel for how RequestFactory interacted with the backend, and some methods and boilerplate to cut down on code.

More links below hopefully.. I'm still a noob so I am limited in # of hyperlinks I can post :)

I learned a lot, and am getting fluent in RequestFactory. I'll do my best to keep an eye out and help out here where I think I can.

Thanks StackOverflow!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top