-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 
Author Message
 Post subject: ClassCastException using detached objects over RMI
PostPosted: Wed Dec 07, 2005 11:56 pm 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
Problem Summary: I'm using detached objects with Hibernate. I have my
application working in a single process architecture and am now trying to separate the
client and server over RMI. When the client sends a request via RMI to the server to
login, the server returns a User object to the client. Before ending the Hibernate Session
on the server, I call Hibernate.initialize() to initialize the portions of User that the client
requires. When RMI tries to deserialize the User object on the client, a
ClassCastException is thrown (shown below): (Note: User is a subclass
of Person):

Information below...

Thank you in advance.

Rick

Hibernate version:

3.1rc1

Mapping documents:

Here are the Hibernate mapping file definitions for Person and Address:
Code:
   <class name="com.toolcafe.common.model.Person" table="person">

      <id name="id" column="id">
         <generator class="com.toolcafe.common.database.UserHiLoGenerator"/>
      </id>            
      <discriminator column="subclass" type="string"/>
      <version name="versionNbr" column="version_nbr" type="long" unsaved-value="null" />
      
      <component name="multiUserData" class="com.toolcafe.common.model.MultiUserData">
         <property name="createdById" column="created_by_id"/>
         <property name="userGroupId" column="user_group_id"/>
         <property name="private" type="boolean"/>
         <property name="lastServerVersionNbr" column="last_server_version_nbr"/>
         <property name="lastClientVersionNbr" column="last_client_version_nbr"/>
         <property name="lastUpdated" column="last_updated" type="timestamp"/>
         <property name="synchComplete" column="synch_complete"/>
         <property name="deleted" type="boolean"/>
         <property name="auditTrail" type="serializable"/>
      </component>
      <property name="firstName" length="32">
         <column name="first_name" index="firstName_index"/>
      </property>
      <property name="lastName" length="32">
         <column name="last_name" index="lastName_index"/>
      </property>
      <property name="middleInitial" length="2"/>
      <property name="workEmail" length="64">
         <column name="work_email" index="workEmail_index"/>
      </property>
      <property name="homeEmail" length="64">
         <column name="home_email" index="homeEmail_index"/>
      </property>
      <property name="salutation" column="salutation" length="32"/>
      <set name="phoneNbrs" cascade="all">
         <key column="person_id"/>
         <one-to-many class="com.toolcafe.common.model.PhoneNbr"/>
      </set>
      <many-to-one name="company" column="company_id" cascade="all"/>
      <many-to-one name="address" column="address_id" cascade="all"/>

      <subclass name="com.toolcafe.common.model.Contact">
         <property name="contactType" column="contact_type" length="64"/>
         <property name="contactSummary" column="contact_summary" length="1024"/>
         <property name="notes" column="notes" length="1024"/>
         <property name="structuredNotes">
            <column name="structured_notes"/>
         </property>
         
         <property name="title" column="title" length="64"/>
         <property name="department" column="department" length="64"/>
         <property name="source" length="64"/>
         <property name="interest" length="64"/>
         <many-to-one name="acctMgr" column="acct_mgr_id" cascade="all"/>
         <many-to-one name="referredBy" column="referred_by_id" cascade="all"/>
         <many-to-one name="assistant" column="assistant_id" cascade="all"/>
         
         <subclass name="com.toolcafe.common.model.User">
            <property name="username" length="32">
               <column name="username" index="username_index"/>
            </property>
            <property name="password" length="32">
               <column name="password" sql-type="VARCHAR(32)"/>
            </property>
            <property name="administrator" column="administrator"/>
            <set name="userGroupPermissions" cascade="all">
               <key column="user_id"/>
               <one-to-many class="com.toolcafe.common.model.UserGroupPermission"/>
            </set>
            <set name="emailAccts" cascade="all">
               <key column="user_id"/>
               <one-to-many class="com.toolcafe.common.model.EmailAcct"/>
            </set>
            <many-to-one name="defaultEmailAcct" column="default_email_acct_id" cascade="all"/>
            <many-to-one name="defaultUserGroup" column="default_user_group_id" cascade="all"/>
            <property name="enabled"/>
         </subclass>
      </subclass>
   </class>
   

   <class name="com.toolcafe.common.model.Address" table="address">

      <id name="id" column="id">
         <generator class="com.toolcafe.common.database.UserHiLoGenerator"/>
      </id>
      <version name="versionNbr" column="version_nbr" type="long" unsaved-value="null" />
      
      <property name="address1" column="address1" length="32"/>
      <property name="address2" column="address2" length="32"/>
      <property name="city" column="city" length="32"/>
      <property name="state" column="state" length="2"/>
      <property name="country" column="country" length="32"/>
      <property name="postalCode" column="postal_code" length="12"/>

   </class>


Here's how I create the SessionFactory:

Code:
      Properties hiProps = new Properties();
      hiProps.setProperty("hibernate.connection.url", dbUrl);
      hiProps.setProperty("hibernate.connection.username", dbCfg.getUsername());
      hiProps.setProperty("hibernate.connection.password", dbCfg.getPassword());
      hiProps.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
      hiProps.setProperty("hibernate.connection.pool_size", String.valueOf(10));
      hiProps.setProperty("hibernate.statement_cache.size", String.valueOf(10));
      hiProps.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
      hiProps.setProperty("hibernate.max_fetch_depth", "3");
      hiProps.setProperty("hibernate.connection.isolation",
            Integer.toString(Connection.TRANSACTION_READ_COMMITTED));
      hiProps.setProperty("hibernate.transaction.factory_class", "org.hibernate.transaction.JDBCTransactionFactory");
      Configuration cfg = new Configuration();
      cfg.addProperties(hiProps);
      cfg.addResource(dbCfg.getHiConfigFile());
      SessionFactory sessionFactory = cfg.buildSessionFactory();


Code between sessionFactory.openSession() and session.close():

Following is a simplification of the actual code, but I think all the relevant parts are included:

Code:
Session s = _sessionFactory.openSession();
Transaction tx = s.beginTransaction();      
// Do a case-insensitive search
List users =
   _session.createQuery(
      "from User as user where upper(user.username) = ?")
      .setString(0, username.toUpperCase())
      .list();

User user = null;
if (users.size() == 1) {
   user = (User) (users.get(0));   
   
   // Test for correct login....
   
   // Prepare the object for the client
   Hibernate.initialize(user);
   
   Hibernate.initialize(user);
   Hibernate.initialize(user.getCompany());
   Hibernate.initialize(user.getAddress());
   Hibernate.initialize(user.getPhoneNbrs());
   
   // Initialize each ScheduledItem
   Hibernate.initialize(user.getScheduledItems());
   for (Iterator siIter = user.getScheduledItems().iterator(); siIter.hasNext(); ) {
      ScheduledItem si = (ScheduledItem)siIter.next();
      
      Hibernate.initialize(si.getAllParticipants());
      for (Iterator opIter = si.getAllParticipants().iterator(); opIter.hasNext(); ) {
         Contact op = (Contact)opIter.next();
         Hibernate.initialize(op.getScheduledItems());
         Hibernate.initialize(op.getPhoneNbrs());
         op.getScheduledItems().iterator().hasNext();
      }
   }
   
   // Initialize the UserGroupPermission objects
   for (Iterator ugpIter = user.getUserGroupPermissions().iterator(); ugpIter.hasNext(); ) {
      UserGroupPermission ugp = (UserGroupPermission)ugpIter.next();
      Hibernate.initialize(ugp.getUserGroup());
   }
   
   // Initialize the EmailAcctS
   for (Iterator emailIter = user.getEmailAccts().iterator(); emailIter.hasNext(); ) {
      EmailAcct emailAcct = (EmailAcct)emailIter.next();
      Hibernate.initialize(emailAcct);
   }
   Hibernate.initialize(user.getDefaultEmailAcct());
   }
   
}

// Commit the txn and close the session
tx.commit();
s.close();

// Return the User to the client
return user;


Full stack trace of any exception that occurs:

java.lang.ClassCastException: cannot assign instance of java.lang.Long to field
com.toolcafe.common.model.Person._address of type
com.toolcafe.common.model.Address in instance of com.toolcafe.common.model.User
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:1977)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1157)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1918)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1836)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1713)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:290)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:139)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:179)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy1.login(Unknown Source)
at com.toolcafe.contact.client.gui.LoginDialog.processServerLogin(LoginDialog.java:327)

Name and version of the database you are using:

HSQLDB version 1.8.0_2

The generated SQL (show_sql=true):

22:42:09,615 DEBUG JDBCTransaction:54 - begin
22:42:09,688 DEBUG JDBCTransaction:59 - current autocommit status: false
22:42:09,690 DEBUG SQL:344 - select user0_.id as id7_, user0_.version_nbr as
version3_7_, user0_.created_by_id as created4_7_, user0_.user_group_id as
user5_7_, user0_.private as private7_, user0_.last_server_version_nbr as last7_7_,
user0_.last_client_version_nbr as last8_7_, user0_.last_updated as last9_7_,
user0_.synch_complete as synch10_7_, user0_.deleted as deleted7_, user0_.auditTrail
as auditTrail7_, user0_.first_name as first13_7_, user0_.last_name as last14_7_,
user0_.middleInitial as middleI15_7_, user0_.work_email as work16_7_,
user0_.home_email as home17_7_, user0_.salutation as salutation7_,
user0_.company_id as company19_7_, user0_.address_id as address20_7_,
user0_.contact_type as contact21_7_, user0_.contact_summary as contact22_7_,
user0_.notes as notes7_, user0_.structured_notes as structured24_7_, user0_.title as
title7_, user0_.department as department7_, user0_.source as source7_,
user0_.interest as interest7_, user0_.acct_mgr_id as acct29_7_, user0_.referred_by_id
as referred30_7_, user0_.assistant_id as assistant31_7_, user0_.username as
username7_, user0_.password as password7_, user0_.administrator as adminis34_7_,
user0_.default_email_acct_id as default35_7_, user0_.default_user_group_id as
default36_7_, user0_.enabled as enabled7_ from person user0_ where
user0_.subclass='com.toolcafe.common.model.User' and upper(user0_.username)=?
22:42:09,710 DEBUG StringType:79 - binding 'RICK' to parameter: 1
22:42:09,714 DEBUG StringType:123 - returning 'rick-32769' as column: id7_
22:42:09,716 DEBUG LongType:123 - returning '0' as column: version3_7_
22:42:09,717 DEBUG StringType:123 - returning 'ROOT_USER' as column: created4_7_
22:42:09,719 DEBUG StringType:116 - returning null as column: user5_7_
22:42:09,722 DEBUG BooleanType:123 - returning 'false' as column: private7_
22:42:09,723 DEBUG LongType:123 - returning '0' as column: last7_7_
22:42:09,772 DEBUG LongType:123 - returning '0' as column: last8_7_
22:42:09,775 DEBUG TimestampType:116 - returning null as column: last9_7_
22:42:09,778 DEBUG BooleanType:123 - returning 'false' as column: synch10_7_
22:42:09,779 DEBUG BooleanType:123 - returning 'false' as column: deleted7_
22:42:09,780 DEBUG SerializableType:116 - returning null as column: auditTrail7_
22:42:09,782 DEBUG StringType:116 - returning null as column: first13_7_
22:42:09,783 DEBUG StringType:116 - returning null as column: last14_7_
22:42:09,784 DEBUG StringType:116 - returning null as column: middleI15_7_
22:42:09,785 DEBUG StringType:123 - returning 'rickhoro@comcast.net' as column: work16_7_
22:42:09,792 DEBUG StringType:116 - returning null as column: home17_7_
22:42:09,794 DEBUG StringType:116 - returning null as column: salutation7_
22:42:09,795 DEBUG StringType:116 - returning null as column: company19_7_
22:42:09,797 DEBUG StringType:116 - returning null as column: address20_7_
22:42:09,798 DEBUG StringType:116 - returning null as column: contact21_7_
22:42:09,799 DEBUG StringType:116 - returning null as column: contact22_7_
22:42:09,801 DEBUG StringType:116 - returning null as column: notes7_
22:42:09,804 DEBUG SerializableType:123 - returning '2c6d8085f3f2809fe3efedaef4efefece3e1e6e5aee3efededefeeaeedefe4e5ecaeceeff4e5f38043430a3facefb5828083cc8088dfe3efeef4e1e3f4f480a3cce3efedaff4efefece3e1e6e5afe3efededefeeafedefe4e5ecafc3efeef4e1e3f4bbcc808cdfece1f3f4d5f0e4e1f4e5e4f48090cceae1f6e1aff5f4e9ecafc4e1f4e5bbcc8086dfeeeff4e5f3f48095cceae1f6e1aff5f4e9ecafd3eff2f4e5e4d3e5f4bbf8f0f0f0f3f28091eae1f6e1aef5f4e9ecaed4f2e5e5d3e5f45d18d013156d07db838080f8f0f0f78480808080f8' as column: structured24_7_
22:42:09,810 DEBUG StringType:116 - returning null as column: title7_
22:42:09,814 DEBUG StringType:116 - returning null as column: department7_
22:42:09,815 DEBUG StringType:116 - returning null as column: source7_
22:42:09,816 DEBUG StringType:116 - returning null as column: interest7_
22:42:09,818 DEBUG StringType:116 - returning null as column: acct29_7_
22:42:09,824 DEBUG StringType:116 - returning null as column: referred30_7_
22:42:09,832 DEBUG StringType:116 - returning null as column: assistant31_7_
22:42:09,833 DEBUG StringType:123 - returning 'rick' as column: username7_
22:42:09,834 DEBUG StringType:123 - returning 'tqNhB' as column: password7_
22:42:09,876 DEBUG BooleanType:123 - returning 'true' as column: adminis34_7_
22:42:09,877 DEBUG StringType:123 - returning 'rick-65537' as column: default35_7_
22:42:09,878 DEBUG StringType:123 - returning 'rick-1' as column: default36_7_
22:42:09,880 DEBUG BooleanType:123 - returning 'true' as column: enabled7_
22:42:09,884 DEBUG SQL:344 - select phonenbrs0_.person_id as person9_1_, phonenbrs0_.id as id1_, phonenbrs0_.id as id0_0_, phonenbrs0_.version_nbr as version2_0_0_, phonenbrs0_.digits as digits0_0_, phonenbrs0_.phone_nbr_type as phone4_0_0_, phonenbrs0_.country_code as country5_0_0_, phonenbrs0_.phone_nbr_str as phone6_0_0_, phonenbrs0_.formatted_phone_nbr as formatted7_0_0_, phonenbrs0_.extension as extension0_0_ from phone_nbr phonenbrs0_ where phonenbrs0_.person_id=?
22:42:09,970 DEBUG StringType:79 - binding 'rick-32769' to parameter: 1
22:42:09,979 DEBUG SQL:344 - select usergroupp0_.user_id as user7_1_, usergroupp0_.id as id1_, usergroupp0_.id as id6_0_, usergroupp0_.user_group_id as user2_6_0_, usergroupp0_.create_allowed as create3_6_0_, usergroupp0_.read_allowed as read4_6_0_, usergroupp0_.update_allowed as update5_6_0_, usergroupp0_.delete_allowed as delete6_6_0_ from user_group_permission usergroupp0_ where usergroupp0_.user_id=?
22:42:09,984 DEBUG StringType:79 - binding 'rick-32769' to parameter: 1
22:42:09,991 DEBUG StringType:123 - returning 'rick-98305' as column: id6_0_
22:42:09,992 DEBUG StringType:123 - returning 'rick-2' as column: user2_6_0_
22:42:09,993 DEBUG BooleanType:123 - returning 'true' as column: create3_6_0_
22:42:09,994 DEBUG BooleanType:123 - returning 'true' as column: read4_6_0_
22:42:09,995 DEBUG BooleanType:123 - returning 'true' as column: update5_6_0_
22:42:09,996 DEBUG BooleanType:123 - returning 'false' as column: delete6_6_0_
22:42:09,996 DEBUG StringType:123 - returning 'rick-32769' as column: user7_1_
22:42:09,997 DEBUG StringType:123 - returning 'rick-98305' as column: id1_
22:42:10,019 DEBUG StringType:123 - returning 'rick-98306' as column: id6_0_
22:42:10,020 DEBUG StringType:123 - returning 'rick-1' as column: user2_6_0_
22:42:10,021 DEBUG BooleanType:123 - returning 'true' as column: create3_6_0_
22:42:10,022 DEBUG BooleanType:123 - returning 'true' as column: read4_6_0_
22:42:10,023 DEBUG BooleanType:123 - returning 'true' as column: update5_6_0_
22:42:10,024 DEBUG BooleanType:123 - returning 'true' as column: delete6_6_0_
22:42:10,025 DEBUG StringType:123 - returning 'rick-32769' as column: user7_1_
22:42:10,026 DEBUG StringType:123 - returning 'rick-98306' as column: id1_
22:42:10,058 DEBUG SQL:344 - select usergroup0_.id as id5_0_, usergroup0_.version_nbr as version2_5_0_, usergroup0_.group_name as group3_5_0_, usergroup0_.group_description as group4_5_0_ from user_group usergroup0_ where usergroup0_.id=?
22:42:10,114 DEBUG StringType:79 - binding 'rick-2' to parameter: 1
22:42:10,119 DEBUG LongType:123 - returning '0' as column: version2_5_0_
22:42:10,120 DEBUG StringType:123 - returning 'Personal' as column: group3_5_0_
22:42:10,121 DEBUG StringType:123 - returning '' as column: group4_5_0_
22:42:10,123 DEBUG SQL:344 - select usergroup0_.id as id5_0_, usergroup0_.version_nbr as version2_5_0_, usergroup0_.group_name as group3_5_0_, usergroup0_.group_description as group4_5_0_ from user_group usergroup0_ where usergroup0_.id=?
22:42:10,135 DEBUG StringType:79 - binding 'rick-1' to parameter: 1
22:42:10,138 DEBUG LongType:123 - returning '0' as column: version2_5_0_
22:42:10,146 DEBUG StringType:123 - returning 'Business' as column: group3_5_0_
22:42:10,147 DEBUG StringType:123 - returning '' as column: group4_5_0_
22:42:10,150 DEBUG SQL:344 - select emailaccts0_.user_id as user12_1_, emailaccts0_.id as id1_, emailaccts0_.id as id8_0_, emailaccts0_.version_nbr as version2_8_0_, emailaccts0_.created_by_id as created3_8_0_, emailaccts0_.user_group_id as user4_8_0_, emailaccts0_.private as private8_0_, emailaccts0_.last_server_version_nbr as last6_8_0_, emailaccts0_.last_client_version_nbr as last7_8_0_, emailaccts0_.last_updated as last8_8_0_, emailaccts0_.synch_complete as synch9_8_0_, emailaccts0_.deleted as deleted8_0_, emailaccts0_.auditTrail as auditTrail8_0_, emailaccts0_.user_id as user12_8_0_, emailaccts0_.acct_name as acct13_8_0_, emailaccts0_.pop3_server as pop14_8_0_, emailaccts0_.username as username8_0_, emailaccts0_.password as password8_0_, emailaccts0_.smtp_server as smtp17_8_0_, emailaccts0_.return_email_addr as return18_8_0_ from email_acct emailaccts0_ where emailaccts0_.user_id=?
22:42:10,154 DEBUG StringType:79 - binding 'rick-32769' to parameter: 1
22:42:10,156 DEBUG StringType:123 - returning 'rick-65537' as column: id8_0_
22:42:10,202 DEBUG LongType:123 - returning '1' as column: version2_8_0_
22:42:10,204 DEBUG StringType:123 - returning 'ROOT_USER' as column: created3_8_0_
22:42:10,210 DEBUG StringType:116 - returning null as column: user4_8_0_
22:42:10,212 DEBUG BooleanType:123 - returning 'false' as column: private8_0_
22:42:10,214 DEBUG LongType:123 - returning '0' as column: last6_8_0_
22:42:10,216 DEBUG LongType:123 - returning '0' as column: last7_8_0_
22:42:10,218 DEBUG TimestampType:116 - returning null as column: last8_8_0_
22:42:10,226 DEBUG BooleanType:123 - returning 'false' as column: synch9_8_0_
22:42:10,241 DEBUG BooleanType:123 - returning 'false' as column: deleted8_0_
22:42:10,243 DEBUG SerializableType:116 - returning null as column: auditTrail8_0_
22:42:10,248 DEBUG StringType:123 - returning 'rick-32769' as column: user12_8_0_
22:42:10,250 DEBUG StringType:123 - returning 'Comcast' as column: acct13_8_0_
22:42:10,252 DEBUG StringType:123 - returning 'mail.comcast.net' as column: pop14_8_0_
22:42:10,253 DEBUG StringType:123 - returning 'rickhoro' as column: username8_0_
22:42:10,256 DEBUG SerializableType:123 - returning '2c6d8085f5f28082dbc330a6e63062dd042c828080f8f08080808880f080e480f180f280b780b480e480b5' as column: password8_0_
22:42:10,258 DEBUG StringType:123 - returning 'smtp.comcast.net' as column: smtp17_8_0_
22:42:10,259 DEBUG StringType:123 - returning 'rickhoro@comcast.net' as column: return18_8_0_
22:42:10,261 DEBUG StringType:123 - returning 'rick-32769' as column: user12_1_
22:42:10,266 DEBUG StringType:123 - returning 'rick-65537' as column: id1_
22:42:10,269 DEBUG JDBCTransaction:103 - commit
22:42:10,274 DEBUG JDBCTransaction:116 - committed JDBC Connection


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 08, 2005 5:02 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
Can you post the code of your Person class ?
These problems usually indicate a different version
of the class on client and server.

_________________
dont forget to rate !


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 08, 2005 8:49 am 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
I don't think this is caused by two different versions of Person. I'm running both client and server in the Eclipse debugger on one machine, and the classpath is the same for both. I'm thinking it might have something to do with the cglib modified proxies, but I can't figure out how to investigate this. I looked on the cglib website and the documentation appears to be pretty sparse, and when looking at the User/Person object in the Eclipse debugger on the server after retrieving it from the database via Hibernate, the _address field is null -- it doesn't have all that cglib proxy mumbo/jumbo. Am I correct in understanding that Hibernate generates a subclass of the data object, e.g. Person when reading an object from the database. Is it the case that the content of a many-to-one relationship field, e.g. _address, is a java.lang.Long value and that is what is passed via RMI to the client -- and causing the ClassCastException when the client tries to de-serialize it?

In any case, here are partial versions of Person and Address (I left out the irrelevant stuff). You'll see it extends TopLevelObject, which in turn extends DataObject. But the _address field is in Person.

Code:
public class Person extends TopLevelObject implements java.io.Serializable {

   // ------------------------------------------------------- Statics

   /** Serializable version id  */
   static final long serialVersionUID = 100L;

   // ------------------------------------------------------- Instance Variables

   /** Unique id of the object - used as the object's primary key in the database */
   private String id;
   /** The user's first name */
   private String _firstName;
   /** The user's last name */
   private String _lastName;
   /** The user's middle initial */
   private String _middleInitial;
   /** The user's work email address */
   private String _workEmail;
   /** The user's home email address */
   private String _homeEmail;
   /** Set of PhoneNbr objects */
   private Set _phoneNbrs = new HashSet();
   /** The person's mailing address */
   private Address _address;
   /** The person's company  */
   private Company _company;
   /** Salutation to use when addressing this person, e.g. Mr., Ms., Dr. */
   private String _salutation;

   // ------------------------------------------------------- Constructors
   
   public Person() {
   }

   /**
    * Require an overridden equals() method
    */
   public boolean equals(Object obj) {
      
      if (!(obj instanceof Person))
         return false;
      
      Person that = (Person) obj;

      if (!ContactUtil.getInstance().idEqual(this, that))
         return false;      
      if (!objEquals(getFirstName(), that.getFirstName()))
         return false;
      if (!objEquals(getLastName(), that.getLastName()))
         return false;
      if (!objEquals(getWorkEmail(), that.getWorkEmail()))
         return false;
      //(TBD) - need to make PhoneNbr an object with a better equals implementation
      if (!checkPhoneNbrsEqual(that))
         return false;
      // Address test
      if (!objEquals(getAddress(), that.getAddress()))
         return false;
      // Company test
      if (!objEquals(getCompany(), that.getCompany()))
         return false;
      // Passed all tests
      return true;
   }

   // ------------------------------------------------------ Instance methods
   
   /**
    * Get the object's unique id
    * @return
    */
   public String getId() {
      return id;
   }

   /**
    * Set the object's unique id
    * @param id
    */
   public void setId(String id) {
      this.id = id;
   }

   /**
    * Return the work email address.
    */
   public String getWorkEmail() {
      return (this._workEmail);
   }
   /**
    * Set the work email address.
    * @param workEmail
    */
   public void setWorkEmail(String workEmail) {
      this._workEmail = workEmail;
   }

   /**
    * Set the user's home email address
    * @return Returns the home email address
    */
   public String getHomeEmail() {
      return _homeEmail;
   }

   /**
    * Set the other email address
    * @param homeEmailAddr The home email address to set.
    */
   public void setHomeEmail(String homeEmail) {
      _homeEmail = homeEmail;
   }

   /**
    * Return the first name.
    */
   public String getFirstName() {
      return (this._firstName);
   }
   /**
    * Set the first name.
    *
    * @param _firstName The new first name
    */
   public void setFirstName(String firstName) {
      this._firstName = firstName;
   }

   /**
    * Return the last name.
    */
   public String getLastName() {
      return (this._lastName);
   }
   /**
    * Set the last name.
    *
    * @param _lastName The new last name
    */
   public void setLastName(String lastName) {
      this._lastName = lastName;
   }

   /**
    * Return the _address.
    */
   public Address getAddress() {
      return (this._address);
   }
   /**
    * Set the _address.
    *
    * @param _address The new _address
    */
   public void setAddress(Address address) {
      this._address = address;
   }

   /**
    * Get phone numbers for this Person
    * @return Set of PhoneNbr objects
    */
   public Set getPhoneNbrs() {
      return _phoneNbrs;
   }

   /**
    * Set phone numbers for this Person
    * @param phoneNbrs Set of PhoneNbr objects
    */
   public void setPhoneNbrs(Set phoneNbrs) {
      _phoneNbrs = phoneNbrs;
   }

   /**
    * Get the salutation to use when addressing this person
    * @return Returns the salutation.
    */
   public String getSalutation() {
      return _salutation;
   }

   /**
    * Set the salutation to use when addressing this person
    * @param salutation The salutation to set.
    */
   public void setSalutation(String salutation) {
      _salutation = salutation;
   }


   /* (non-Javadoc)
    * @see com.toolcafe.contact.model.DataObject#getVersionNbr()
    */
   public Long getVersionNbr() {
      // TODO Auto-generated method stub
      return super.getVersionNbr();
   }

   /* (non-Javadoc)
    * @see com.toolcafe.contact.model.DataObject#setVersionNbr(long)
    */
   public void setVersionNbr(Long versionNbr) {
      // TODO Auto-generated method stub
      super.setVersionNbr(versionNbr);
   }

   /* (non-Javadoc)
    * @see com.toolcafe.contact.model.DataObject#getTypeName()
    */
   public String getTypeName() {
      return _resMgr.getString("typeName");
   }

}

public class Address extends DataObject implements java.io.Serializable {

   // ------------------------------------------------------- Statics
   /**
    * Serializable version _id
    * When evolving this class with compatible changes, copy this version _id
    * to the new class
    */
   static final long serialVersionUID = 100L;

   // ----------------------------------------------------- Instance variables
   
   /** Unique _id of the object - used as the object's primary key in the database */
   private String _id;
   /** 1st address line */
   private String _address1;
   /** 2nd address line */
   private String _address2;
   /** City */
   private String _city;
   /** State - contains the entire _state name */
   private String _state;
   /** Country name */
   private String _country;
   /** Postal code */
   private String _postalCode;

   // ----------------------------------------------------- Constructors

   public Address() {
   }

   /**
    * Construct the address
    * @param _address1 Address line 1
    * @param _address2 Address line 2
    * @param _city The _city
    * @param _state The _state
    * @param _country The _country
    * @param _postalCode Postal/ZIP code
    */
   public Address(
      String address1,
      String address2,
      String city,
      String state,
      String country,
      String postalCode) {

      this._address1 = address1;
      this._address2 = address2;
      this._city = city;
      this._state = state;
      this._country = country;
      this._postalCode = postalCode;
   }
   

   // ----------------------------------------------------- Instance methods
   
   /**
    * Get the object's unique _id
    * @return
    */
   public String getId() {
      return _id;
   }

   /**
    * Set the object's unique _id
    * @param _id
    */
   public void setId(String id) {
      this._id = id;
   }

   /**
    * Set _address1
    */
   public void setAddress1(String address1) {
      this._address1 = address1;
   }
   /**
    * Get _address1
    */
   public String getAddress1() {
      return this._address1;
   }

   /**
    * Set _address2
    */
   public void setAddress2(String address2) {
      this._address2 = address2;
   }
   /**
    * Get _address2
    */
   public String getAddress2() {
      return this._address2;
   }

   /**
    * Set _city
    */
   public void setCity(String city) {
      this._city = city;
   }
   /**
    * Get _city
    */
   public String getCity() {
      return this._city;
   }

   /**
    * Set _state 2-letter code
    */
   public void setState(String state) {
      this._state = state;
   }
   /**
    * Get _state 2-letter code
    */
   public String getState() {
      return this._state;
   }

   /**
    * Set _country code
    */
   public void setCountry(String country) {
      this._country = country;
   }
   /**
    * Get _country code
    */
   public String getCountry() {
      return this._country;
   }

   /**
    * Set postal code
    */
   public void setPostalCode(String postalCode) {
      this._postalCode = postalCode;
   }
   /**
    * Get postal code
    */
   public String getPostalCode() {
      return this._postalCode;
   }

   /* (non-Javadoc)
    * @see com.toolcafe.contact.model.DataObject#getVersionNbr()
    */
   public Long getVersionNbr() {
      // TODO Auto-generated method stub
      return super.getVersionNbr();
   }

   /* (non-Javadoc)
    * @see com.toolcafe.contact.model.DataObject#setVersionNbr(long)
    */
   public void setVersionNbr(Long versionNbr) {
      // TODO Auto-generated method stub
      super.setVersionNbr(versionNbr);
   }

   /* (non-Javadoc)
    * @see com.toolcafe.contact.model.DataObject#getTypeName()
    */
   public String getTypeName() {
      return _resMgr.getString("typeName");
   }

}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 08, 2005 12:36 pm 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
I think that cglib is creating a subclass.
You can try using reflection api instead of cglib.
Put a file hibernate.properties in classpath
with content:

hibernate.cglib.use_reflection_optimizer=false

Hope this helps.

_________________
dont forget to rate !


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 08, 2005 1:07 pm 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
Unfortunately this did not work. I still get the same ClassCastException.

Given the description in the User Guide, " Enables use of CGLIB instead of runtime reflection (System-level property). Reflection can sometimes be useful when troubleshooting, note that Hibernate always requires CGLIB even if you turn off the optimizer. You can not set this property in hibernate.cfg.xml.", I configured this programmatically using the following line of code:

hiProps.setProperty("hibernate.cglib.use_reflection_optimizer", String.valueOf(false));


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 08, 2005 1:37 pm 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
I tried setting the address field mapping with lazy="false". According to the docs, this eliminates proxying, which I thought would result in the serialization working correctly. Unfortunately, it did not. Any other ideas greatly appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 08, 2005 6:43 pm 
Regular
Regular

Joined: Tue Jun 22, 2004 8:01 pm
Posts: 106
Location: PowderTown, Utah, USA
The problem is proxy objects induced via CGLIB. While there are good object oriented ways around this (in other words, redesign and try to not use instanceof and class casts) sometimes you're stuck with code you can't quickly retrofit.

There are a few ways to hack around this problem. I detail them in this post:

http://forum.hibernate.org/viewtopic.php?t=947035

The second option (using "unproxy()" methods on a base class) is the simplest. Stay away from these unless you really have to.

Typecasts and Instanceof are both undesireable and are almost always an indication that you need more time on the object model and design.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 5:00 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Hibernate replaces proxy with this stuff in object stream http://cvs.sourceforge.net/viewcvs.py/h ... iew=markup

but I do not see it on statck trace, try to change serial version to make sure you have same classes on client ad on server.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 8:20 am 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
baliukas,

It sounds like the proxy replacement with SerializableProxy.java should be automatic. Is this
the case? If so, can you think of any reason why it would not be happening in my
application?

I can't see how I might have different classes on the client and server -- I'm running both
client and server from the same Eclipse project. I have hardcoded serializable version
numbers in each class.

Can you offer any ideas on how to debug this problem? Debugging into RMI is problematic
because Sun has yet to provide an rt.jar with full debugging information -- aahh! But I do
have the Hibernate sources if that will help here.

Thanks very much. Please, a little more help here would be great. I'll be sure to assign
credits to those who help me solve this problem.

Ri ck


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 8:29 am 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
baliukas,

I looked at the SerializableProxy code. The constructor is only called from one place and
ends at a dead end:

org.hibernate.proxy.BasicLazyInitializer.getReplacement() calls:
org.hibernate.proxy.CGLIBLazyInitializer.serializableProxy() calls:
SerializableProxy(...) constructor

If this is doing something useful, I assume that cglib is generating some sort of code here
to actually perform the actions. Is this the case? Do you know how this code is supposed
to get actioned?

Rick


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 9:37 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Hibernate adds "writeReplace" for proxy class, this method writes stuff to recreate proxy on client. Recreated proxy has no session and it will throw LazyInitializationException if you will call it (it is kind of marker, client must not access serialized proxy, it dead after serialization).
You can debug it without RMI stuff, just try to serialize proxy to byte array using IO wrapprs (byte arry input/output streams and object stream).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 09, 2005 9:51 am 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
BTW there are two cases:
1. if proxy is initialized then it will be replaced with original object (no proxy on client)
2. if proxy is unitialized then dead proxy will be recreated on client.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 17, 2005 6:13 pm 
Beginner
Beginner

Joined: Wed Oct 15, 2003 1:31 pm
Posts: 25
Thank you to both baliukas and cardsharp. Although neither of your postings solved my
problem, both helped guide me to understand more about the whole proxying approach in
Hibernate so I awarded each of you 1 credit.

My problem is solved. Turned out to be completely unrelated to Hibernate. I am using a
readObject() method in the superclass of my data objects that get passed over RMI
between my client and server. However, I forgot to make a call to
stream.defaultReadObject() at the beginning of readObject(). Well...as you may know, this
caused the instance variables in the superclass object to not be read! When they are finally
read to restore the subclass object, the superclass' instance variables are assigned to the
subclass' instance variables. This results in my ClassCastException. Ahh!

I'm glad to say that all is now well, and I'm glad this is just user error on my part, rather than
a bug in Hibernate that I'd have to lobby to get fixed.

_________________
Rick Horowitz
---------
Please remember to rate...


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 13 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.