-->
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: Weird error with setter order
PostPosted: Wed Mar 17, 2010 10:06 pm 
Newbie

Joined: Tue Jun 08, 2004 7:44 pm
Posts: 12
I have the following domain object with overloaded setter methods.

Code:
public class Customer extends AbstractCustomerValue {
...
   public void setKey(UUID key) {
      this.key = key.toString();
   }
   
   public void setKey(String key) {
      this.key = key
   }   
}

public abstract class AbstractCustomerValue {
...
protected String key;
...
}


When I try to load this object from the database, I get the following error. However when I interchange the setters as below it works fine
Code:
public class Customer extends AbstractCustomerValue {
...
   public void setKey(String key) {
      this.key = key;
   }   

   public void setKey(UUID key) {
      this.key = key.toString();
   }

}

CustomerHome:
Code:
....
   public Customer findById(java.lang.String id) {
      log.debug("getting Customer instance with id: " + id);
      try {
         Session session = sessionFactory.getCurrentSession();
         session.beginTransaction();
         Customer instance = (Customer) session
               .get("com.xyz.coherence.model.Customer", id);
         if (instance == null) {
            log.debug("get successful, no instance found");
         } else {
            log.debug("get successful, instance found");
         }
         session.close();
         return instance;
      } catch (RuntimeException re) {
         log.error("get failed", re);
         throw re;
      }
   }

..........



ERROR:
4781 [main] ERROR org.hibernate.property.BasicPropertyAccessor - IllegalArgumentException in class: com.xyz.coherence.model.Customer, setter method of property: key
4781 [main] ERROR org.hibernate.property.BasicPropertyAccessor - expected type: java.util.UUID, actual value: java.lang.String
4781 [main] INFO org.hibernate.event.def.DefaultLoadEventListener - Error performing load command
org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.xyz.coherence.model.Customer.key
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:128)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setIdentifier(AbstractEntityTuplizer.java:227)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate(AbstractEntityTuplizer.java:368)
at org.hibernate.persister.entity.AbstractEntityPersister.instantiate(AbstractEntityPersister.java:3620)
at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1303)
at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1292)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1323)
at org.hibernate.loader.Loader.getRow(Loader.java:1230)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:603)
at org.hibernate.loader.Loader.doQuery(Loader.java:724)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1885)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3062)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:906)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:843)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:342)
at $Proxy0.get(Unknown Source)
at com.xyz.jpa.CustomerHome.findById(CustomerHome.java:101)
at com.xyz.jpa.CustomerHome.main(CustomerHome.java:150)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
... 29 more
Mar 17, 2010 6:45:18 PM com.xyz.jpa.CustomerHome findById
SEVERE: get failed
org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.xyz.coherence.model.Customer.key
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:128)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setIdentifier(AbstractEntityTuplizer.java:227)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate(AbstractEntityTuplizer.java:368)
at org.hibernate.persister.entity.AbstractEntityPersister.instantiate(AbstractEntityPersister.java:3620)
at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1303)
at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1292)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1323)
at org.hibernate.loader.Loader.getRow(Loader.java:1230)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:603)
at org.hibernate.loader.Loader.doQuery(Loader.java:724)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1885)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3062)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:906)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:843)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:342)
at $Proxy0.get(Unknown Source)
at com.xyz.jpa.CustomerHome.findById(CustomerHome.java:101)
at com.xyz.jpa.CustomerHome.main(CustomerHome.java:150)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
... 29 more


HBM:
Code:
<hibernate-mapping>
    <class name="com.xyz.coherence.model.Customer" table="customer" catalog="xyz">
        <id name="key" type="string">
            <column name="CUSTOMERID" length="30" />
            <generator class="assigned" />
        </id>
        <property name="firstName" type="string">
            <column name="FIRSTNAME" length="200" />
        </property>
        <property name="middleName" type="string">
            <column name="MIDDLENAME" length="200" />
        </property>
        <property name="lastName" type="string">
            <column name="LASTNAME" length="200" />
        </property>
        <property name="source" type="string">
            <column name="SOURCE" length="50" />
        </property>
    </class>
</hibernate-mapping>

Does the order of the setters matter while I load the object from the database?


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 4:05 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
Does the order of the setters matter?


Yes. In a certain way.

Below a snippet of class org.hibernate.property.BasicPropertyAccessor.
As you can see from the code hibernate proceeds in following way:
- per reflection it searches for methods with name "setKey" and one parameter (this returns 2 methods in your case)
- the appropriate return type hibernate tries to establish looking for a relative getter method.
Is there no relative getter method found (it's your case) then the first potential setter method is taken and returned.
- as reflection returns the methods in the order they are declared in code, the first potential setter is the method
which you declare as first in your code ;-)


Code:

private static Method setterMethod(Class theClass, String propertyName) {

      BasicGetter getter = getGetterOrNull(theClass, propertyName);
      Class returnType = (getter==null) ? null : getter.getReturnType();

      Method[] methods = theClass.getDeclaredMethods();
      Method potentialSetter = null;
      for (int i=0; i<methods.length; i++) {
         String methodName = methods[i].getName();

         if ( methods[i].getParameterTypes().length==1 && methodName.startsWith("set") ) {
            String testStdMethod = Introspector.decapitalize( methodName.substring(3) );
            String testOldMethod = methodName.substring(3);
            if ( testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName) ) {
               potentialSetter = methods[i];
               if ( returnType==null || methods[i].getParameterTypes()[0].equals(returnType) ) {
                  return potentialSetter;
               }
            }
         }
      }
      return potentialSetter;
   }


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 4:31 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Just a not related to the statement "as reflection returns the methods in the order they are declared in code". This is not an absolute truth. The javadoc for Class.getDeclaredMethods() says:

Code:
The elements in the array returned are not sorted and are not in any particular order.


In fact, I ran into a similar issue with Tomcat and a taglib class which also had overloaded setter methods. Everything worked fine with Sun's java engine, but I got a similar error when I tried it with IBM's java engine. It turned out that IBM's implementation returned the methods in a different order. So... the safest way is to use a different name for the method. For example: setUUIDKey


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 4:33 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Hi Nordborg,

thanks for correcting me!
Sometimes I make wrong presumptions, I must take more care in future ;-)


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 5:15 am 
Newbie

Joined: Tue Jun 08, 2004 7:44 pm
Posts: 12
duplicate


Last edited by sairam313 on Thu Mar 18, 2010 5:16 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 5:16 am 
Newbie

Joined: Tue Jun 08, 2004 7:44 pm
Posts: 12
Thanks for your replies.

So even with orders changed, I can get this error in a different environment? That makes me nervous.

Forcing me to change my domain model to overcome this problem doesn't seem like a good ORM solution. I wonder if eclipselink/JPA has the same issue (I don't remember coming across this limitation before)

Rgds,
Sairam


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 5:36 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
Forcing me to change my domain model to overcome


Do you can't use a different name for the method (setUUIDKey) as Nordborg suggests without changing your domain model ?

According to what I explained in my first post, another possibility to get rid of the problem,
would be to additionally define the getter-method :

Code:
public String getKey() {
      return this.key;
   }   


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 5:40 am 
Newbie

Joined: Tue Jun 08, 2004 7:44 pm
Posts: 12
I can change the method without changing the domain model but the rule to not have overloaded methods with different datatype arguments seems too limiting


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 5:56 am 
Expert
Expert

Joined: Tue Jun 16, 2009 3:36 am
Posts: 990
Quote:
the rule to not have overloaded methods with different datatype arguments seems too limiting


Once again (expressed in other words):
you can successfully overload the setter methods as long you define also the correlative public getter method !
(Why don't define the getter method ?)


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 6:30 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
I am not really sure why Hibernate can't locate the correct setter method. It should match the type of the parameter in the setKey() method with the return type of the getKey() method. In which class is your getKey() method declared?

There is a JIRA issue that may be related to this: http://opensource.atlassian.com/project ... e/HHH-2268


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 5:27 pm 
Newbie

Joined: Tue Jun 08, 2004 7:44 pm
Posts: 12
My getKey method is in the superclass and it returns a wrapper object. It doesn't return an UUID or a String. I want it that way for my other subsystems to work.
Code:
public abstract class AbstractCustomerValue implements CoherenceValue, PortableObject {
...
   protected String key;
   /**
    * Returns a UUID based key
    */
   public CoherenceKey getKey() {
      return new CoherenceKeyImpl(key);
   }
   
   public void setKey(String key) {
      this.key = key;
   }   
   
   public void setKey(UUID key) {
      this.key = key.toString();
   }
...
}


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 6:17 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
My getKey method is in the superclass and it returns a wrapper object. It doesn't return an UUID or a String.


Ok, that's the problem. Hibernate is looking for a setter method with the same parameter type as the return type of the getter method. Since they don't match the result is random. I am a bit surprised that no error shows up earlier. After all, you have mapped 'key' as a 'string' in the mapping document, and Hibernate expects String getKey() and setKey(String).

If you really, really want to keep it this way the only way forward is to implement your own PropertyAccessor and specify that in the mapping document.

Code:
<id name="key" access="your.custom.PropertyAccessor" .... >


The API is here: http://docs.jboss.org/hibernate/stable/ ... essor.html


Top
 Profile  
 
 Post subject: Re: Weird error with setter order
PostPosted: Thu Mar 18, 2010 6:27 pm 
Newbie

Joined: Tue Jun 08, 2004 7:44 pm
Posts: 12
Thanks Nordborg. I will implement a new PropertyAccessor


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.