-->
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.  [ 5 posts ] 
Author Message
 Post subject: GUI Application: CGLIB Event property missing
PostPosted: Sat Nov 04, 2006 7:00 am 
Newbie

Joined: Sat Nov 04, 2006 6:34 am
Posts: 2
Hi everybody,

first I'll describe the scenario:

I have two POJOs A and B (A extends B). B has some methods to set a PropertyChangeListener. When this method is called it creates, if not existing, a new private object changeSupport which holds the listeners.

Code:
    public final synchronized void addPropertyChangeListener(
                                            PropertyChangeListener listener) {
        if (listener == null) {
            return;
        }
        if (changeSupport == null) {
            changeSupport = new ExtendedPropertyChangeSupport(this);
        }
        changeSupport.addPropertyChangeListener(listener);
    }


Now I retrieve an object A with hibernate and set the listeners. When I do so the debugger shows that A ist in instanceof A$$EnhanceByCGLIB$$. Later when the GUI calls a setter method (e.g. setAge()) of A to change the field the firePropertyChange method is called.

Code:
   
   public void setAge(Integer newAge) {
      Integer oldAge = age;
      age = newAge;
      if (newAge != null && !newAge.equals(oldAge)) {
         firePropertyChange(AGE, oldAge, newAge);
      }
   }


And here comes the problem. Inside this method the debugger shows me that the object is an instance of A. All values are set except the changeSupport.
What is going wrong? Is ist because neither A nor B have a setter or getter for changeSupport?

Here the dao methode for loading a patient.
Code:
   private Patient loadPatientById(Long id) {
      Patient result;
      Session session = HibernateUtil.getSessionFactory().getCurrentSession();
      session.beginTransaction();
      result = (Patient) session.load(Patient.class, id);
      // TODO remove hack to avoid close session prob
      result.hashCode();
      Hibernate.initialize(result);
      session.getTransaction().commit();
      return result;
   }


I am using hibernate 3.20 with mysql 4.1.21 as DB

Thank you for any hint! I tried to keep it as short as possible. Please let me know if you need some additional information.

Kif


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 5:47 pm 
Senior
Senior

Joined: Tue Mar 09, 2004 2:38 pm
Posts: 141
Location: Lowell, MA USA
Your changeSupport will be null because you only initializing changeSupport only if you add a listener:

Code:
public final synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
        if (listener == null) {
            return;
        }
        if (changeSupport == null) {
            changeSupport = new ExtendedPropertyChangeSupport(this);
        }
        changeSupport.addPropertyChangeListener(listener);
    }


This will cause any setter to throw a NullPointerException when as setter is called if no listeners have yet been added. In applications I have created, when you load the entity for the first time, it will have no listeners initially.

I generally initialize the field when I declare it, such that:

Code:
private ExtendedPropertyChangeSupport changeSupport = new ExtendedPropertyChangeSupport(this);


Then your addListener method would look like:

Code:
public void addPropertyChangeListener(PropertyChangeListener listener) {
        if (listener == null) {
            return;
        }
        changeSupport.addPropertyChangeListener(listener);
    }



There is really no performance penalty in doing this and it is less error prone.

Ryan-

_________________
Ryan J. McDonough
http://damnhandy.com

Please remember to rate!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 05, 2006 8:45 am 
Newbie

Joined: Sat Nov 04, 2006 6:34 am
Posts: 2
Thanks for ur answer Ryan but I think this will not solve my problem. Without hibernate everything is working perfectly.
My problem is that when I load an object with hibernate it returns a proxy object wrapping the real object. Now I call the addPropertyChangeListener() method on the proxy. The debugger shows me that a changeSupport object was created - everything fine. But later when a setter is called (on the real object) it doesn't have a reference to changeSupport (changeSupport is null for the real object) anymore.
So I think my problem is that this reference isn't passed from the proxy to the object. As work around (please don't shoot :)) I retrieve the wrapped object from the proxy and call the addPropertyChangeListener() method directly on the wrapped object. But I think there should be a better way to do this (most likely it's because I miss some important informations about how hibernate works).

Thanks

Kif


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 05, 2006 11:44 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
the setter is called by hibernate before the actual addPropertyXXX is executed.

Why ? well, because we need to load the state into the object before calling your wanted method on it...so do as previously suggested; make your code in the setters null safe.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 05, 2006 12:50 pm 
Senior
Senior

Joined: Tue Mar 09, 2004 2:38 pm
Posts: 141
Location: Lowell, MA USA
Kif,

Generally a true JavaBean will have property change support initialized when the bean in created. There is nothing to gain performance-wise by lazily initializing an instance of property change support. I have written a few AOP examples of how to use PropertyChangeSupport with Hibernate objects:

http://www.damnhandy.com/?page_id=17
https://handyaspects.dev.java.net/

In both cases, PropertyChangeSupport is initialized when the field is declared. The reason for doing this is so that the instance is initialized prior to Hibernate calling any setters. With Hibernated objects, these aspects work flawlessly and integrate nicely with the JGoodies Binding framework.

Also, if someone gives you advice for free and it will only take a few seconds to test it out: why not give it a shot before saying "you don't think it will work". You'll only know that for sure once you actually try it and it fails.

Ryan-

_________________
Ryan J. McDonough
http://damnhandy.com

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.  [ 5 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.